@sapui5/sap.fe.core 1.92.0 → 1.93.3

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 (84) hide show
  1. package/package.json +2 -3
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +2 -2
  4. package/src/sap/fe/core/AppComponent.js +21 -1
  5. package/src/sap/fe/core/CommonUtils.js +130 -48
  6. package/src/sap/fe/core/ExtensionAPI.js +238 -226
  7. package/src/sap/fe/core/PageController.js +5 -2
  8. package/src/sap/fe/core/TemplateComponent.js +1 -0
  9. package/src/sap/fe/core/TransactionHelper.js +35 -8
  10. package/src/sap/fe/core/actions/draft.js +1 -1
  11. package/src/sap/fe/core/actions/messageHandling.js +18 -6
  12. package/src/sap/fe/core/actions/operations.js +17 -41
  13. package/src/sap/fe/core/controllerextensions/EditFlow.js +127 -43
  14. package/src/sap/fe/core/controllerextensions/InternalRouting.js +11 -11
  15. package/src/sap/fe/core/controllerextensions/KPIManagement.js +417 -0
  16. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +399 -0
  17. package/src/sap/fe/core/controllerextensions/PageReady.js +2 -3
  18. package/src/sap/fe/core/controllerextensions/PageReady.ts +1 -1
  19. package/src/sap/fe/core/controllerextensions/Share.js +102 -66
  20. package/src/sap/fe/core/controllerextensions/SideEffects.js +60 -14
  21. package/src/sap/fe/core/controllerextensions/SideEffects.ts +53 -12
  22. package/src/sap/fe/core/controllerextensions/ViewState.js +18 -18
  23. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +13 -0
  24. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +68 -2
  25. package/src/sap/fe/core/converters/ConverterContext.js +15 -1
  26. package/src/sap/fe/core/converters/ConverterContext.ts +11 -0
  27. package/src/sap/fe/core/converters/ManifestSettings.js +1 -1
  28. package/src/sap/fe/core/converters/ManifestSettings.ts +14 -2
  29. package/src/sap/fe/core/converters/ManifestWrapper.js +14 -14
  30. package/src/sap/fe/core/converters/ManifestWrapper.ts +13 -12
  31. package/src/sap/fe/core/converters/MetaModelConverter.js +32 -2
  32. package/src/sap/fe/core/converters/MetaModelConverter.ts +39 -2
  33. package/src/sap/fe/core/converters/annotations/DataField.js +10 -6
  34. package/src/sap/fe/core/converters/annotations/DataField.ts +9 -5
  35. package/src/sap/fe/core/converters/common/AnnotationConverter.js +14 -4
  36. package/src/sap/fe/core/converters/controls/Common/Action.js +25 -15
  37. package/src/sap/fe/core/converters/controls/Common/Action.ts +33 -19
  38. package/src/sap/fe/core/converters/controls/Common/Criticality.js +50 -0
  39. package/src/sap/fe/core/converters/controls/Common/Criticality.ts +33 -0
  40. package/src/sap/fe/core/converters/controls/Common/Form.js +2 -3
  41. package/src/sap/fe/core/converters/controls/Common/Form.ts +1 -2
  42. package/src/sap/fe/core/converters/controls/Common/KPI.js +181 -0
  43. package/src/sap/fe/core/converters/controls/Common/KPI.ts +220 -0
  44. package/src/sap/fe/core/converters/controls/Common/Table.js +121 -59
  45. package/src/sap/fe/core/converters/controls/Common/Table.ts +130 -62
  46. package/src/sap/fe/core/converters/controls/ObjectPage/HeaderFacet.js +5 -4
  47. package/src/sap/fe/core/converters/controls/ObjectPage/HeaderFacet.ts +9 -3
  48. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +62 -7
  49. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +58 -6
  50. package/src/sap/fe/core/converters/helpers/Aggregation.js +86 -11
  51. package/src/sap/fe/core/converters/helpers/Aggregation.ts +79 -8
  52. package/src/sap/fe/core/converters/helpers/BindingHelper.js +44 -2
  53. package/src/sap/fe/core/converters/helpers/BindingHelper.ts +43 -2
  54. package/src/sap/fe/core/converters/helpers/ID.js +3 -1
  55. package/src/sap/fe/core/converters/helpers/ID.ts +1 -0
  56. package/src/sap/fe/core/converters/helpers/IssueManager.js +8 -2
  57. package/src/sap/fe/core/converters/helpers/IssueManager.ts +7 -1
  58. package/src/sap/fe/core/converters/helpers/SelectionVariantHelper.js +93 -0
  59. package/src/sap/fe/core/converters/helpers/SelectionVariantHelper.ts +92 -0
  60. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +102 -23
  61. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +111 -17
  62. package/src/sap/fe/core/converters/templates/ListReportConverter.js +44 -5
  63. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +39 -2
  64. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +41 -30
  65. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +47 -30
  66. package/src/sap/fe/core/designtime/AppComponent.designtime.js +4 -1
  67. package/src/sap/fe/core/formatters/CriticalityFormatter.js +77 -0
  68. package/src/sap/fe/core/formatters/CriticalityFormatter.ts +58 -0
  69. package/src/sap/fe/core/formatters/KPIFormatter.js +103 -0
  70. package/src/sap/fe/core/formatters/KPIFormatter.ts +88 -0
  71. package/src/sap/fe/core/fpm/manifest.json +1 -3
  72. package/src/sap/fe/core/helpers/BindingExpression.js +161 -97
  73. package/src/sap/fe/core/helpers/BindingExpression.ts +188 -117
  74. package/src/sap/fe/core/library.js +1 -1
  75. package/src/sap/fe/core/messagebundle.properties +45 -1
  76. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +3 -1
  77. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -0
  78. package/src/sap/fe/core/services/RoutingServiceFactory.js +30 -8
  79. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +16 -4
  80. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +13 -3
  81. package/src/sap/fe/core/templating/DataModelPathHelper.js +7 -3
  82. package/src/sap/fe/core/templating/DataModelPathHelper.ts +7 -2
  83. package/src/sap/fe/core/templating/UIFormatters.js +1 -5
  84. package/src/sap/fe/core/templating/UIFormatters.ts +0 -3
@@ -0,0 +1,181 @@
1
+ /*!
2
+ * SAP UI development toolkit for HTML5 (SAPUI5)
3
+ * (c) Copyright 2009-2021 SAP SE. All rights reserved
4
+ */
5
+ sap.ui.define(["../../helpers/ID", "sap/fe/core/templating/PropertyHelper", "sap/fe/core/formatters/TableFormatterTypes", "../../helpers/Aggregation", "sap/fe/core/converters/helpers/IssueManager", "./Criticality", "sap/fe/core/converters/helpers/SelectionVariantHelper"], function (ID, PropertyHelper, TableFormatterTypes, Aggregation, IssueManager, Criticality, SelectionVariantHelper) {
6
+ "use strict";
7
+
8
+ var _exports = {};
9
+ var getFilterDefinitionsFromSelectionVariant = SelectionVariantHelper.getFilterDefinitionsFromSelectionVariant;
10
+ var getMessageTypeFromCriticalityType = Criticality.getMessageTypeFromCriticalityType;
11
+ var IssueType = IssueManager.IssueType;
12
+ var IssueSeverity = IssueManager.IssueSeverity;
13
+ var IssueCategory = IssueManager.IssueCategory;
14
+ var AggregationHelper = Aggregation.AggregationHelper;
15
+ var MessageType = TableFormatterTypes.MessageType;
16
+ var isPathExpression = PropertyHelper.isPathExpression;
17
+ var KPIID = ID.KPIID;
18
+
19
+ function createKPIDefinition(kpiName, kpiConfig, converterContext) {
20
+ var _targetKPI$Detail;
21
+
22
+ var kpiConverterContext = converterContext.getConverterContextFor("/" + kpiConfig.entitySet);
23
+ var aKPIAnnotations = kpiConverterContext.getAnnotationsByTerm("UI", "com.sap.vocabularies.UI.v1.KPI");
24
+ var targetKPI = aKPIAnnotations.find(function (kpi) {
25
+ return kpi.qualifier === kpiConfig.qualifier;
26
+ });
27
+ var aggregationHelper = new AggregationHelper(kpiConverterContext.getEntityType(), kpiConverterContext);
28
+
29
+ if (targetKPI && ((_targetKPI$Detail = targetKPI.Detail) === null || _targetKPI$Detail === void 0 ? void 0 : _targetKPI$Detail.DefaultPresentationVariant) && aggregationHelper.isAnalyticsSupported()) {
30
+ var _targetValueProperty$, _targetValueProperty$3;
31
+
32
+ var kpiID = KPIID(kpiName); // Datapoint
33
+
34
+ var datapointAnnotation = targetKPI.DataPoint;
35
+ var datapointProperty = datapointAnnotation.Value.$target;
36
+
37
+ if (!aggregationHelper.isPropertyAggregatable(datapointProperty)) {
38
+ // The main property of the KPI is not aggregatable --> We can't calculate its value so we ignore the KPI
39
+ converterContext.getDiagnostics().addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.MAIN_PROPERTY_NOT_AGGREGATABLE + kpiConfig.qualifier);
40
+ return undefined;
41
+ }
42
+
43
+ var kpiDef = {
44
+ id: kpiID,
45
+ entitySet: kpiConfig.entitySet,
46
+ datapoint: {
47
+ propertyPath: datapointAnnotation.Value.path,
48
+ annotationPath: kpiConverterContext.getEntitySetBasedAnnotationPath(datapointAnnotation.fullyQualifiedName)
49
+ },
50
+ selectionVariantFilterDefinitions: targetKPI.SelectionVariant ? getFilterDefinitionsFromSelectionVariant(targetKPI.SelectionVariant) : undefined
51
+ }; // Unit or currency
52
+
53
+ var targetValueProperty = datapointAnnotation.Value.$target;
54
+
55
+ if ((_targetValueProperty$ = targetValueProperty.annotations.Measures) === null || _targetValueProperty$ === void 0 ? void 0 : _targetValueProperty$.ISOCurrency) {
56
+ var _targetValueProperty$2;
57
+
58
+ var currency = (_targetValueProperty$2 = targetValueProperty.annotations.Measures) === null || _targetValueProperty$2 === void 0 ? void 0 : _targetValueProperty$2.ISOCurrency;
59
+
60
+ if (isPathExpression(currency)) {
61
+ kpiDef.datapoint.unit = {
62
+ value: currency.$target.name,
63
+ isCurrency: true,
64
+ isPath: true
65
+ };
66
+ } else {
67
+ kpiDef.datapoint.unit = {
68
+ value: currency.toString(),
69
+ isCurrency: true,
70
+ isPath: false
71
+ };
72
+ }
73
+ } else if ((_targetValueProperty$3 = targetValueProperty.annotations.Measures) === null || _targetValueProperty$3 === void 0 ? void 0 : _targetValueProperty$3.Unit) {
74
+ var _targetValueProperty$4;
75
+
76
+ var unit = (_targetValueProperty$4 = targetValueProperty.annotations.Measures) === null || _targetValueProperty$4 === void 0 ? void 0 : _targetValueProperty$4.Unit;
77
+
78
+ if (isPathExpression(unit)) {
79
+ kpiDef.datapoint.unit = {
80
+ value: unit.$target.name,
81
+ isCurrency: false,
82
+ isPath: true
83
+ };
84
+ } else {
85
+ kpiDef.datapoint.unit = {
86
+ value: unit.toString(),
87
+ isCurrency: false,
88
+ isPath: false
89
+ };
90
+ }
91
+ } // Criticality
92
+
93
+
94
+ if (datapointAnnotation.Criticality) {
95
+ if (typeof datapointAnnotation.Criticality === "object") {
96
+ // Criticality is a path --> check if the corresponding property is aggregatable
97
+ var criticalityProperty = datapointAnnotation.Criticality.$target;
98
+
99
+ if (aggregationHelper.isPropertyAggregatable(criticalityProperty)) {
100
+ kpiDef.datapoint.criticalityPath = datapointAnnotation.Criticality.path;
101
+ } else {
102
+ // The property isn't aggregatable --> we ignore it
103
+ kpiDef.datapoint.criticalityValue = MessageType.None;
104
+ }
105
+ } else {
106
+ // Criticality is an enum Value --> get the corresponding static value
107
+ kpiDef.datapoint.criticalityValue = getMessageTypeFromCriticalityType(datapointAnnotation.Criticality);
108
+ }
109
+ } else if (datapointAnnotation.CriticalityCalculation) {
110
+ kpiDef.datapoint.criticalityCalculationMode = datapointAnnotation.CriticalityCalculation.ImprovementDirection;
111
+ kpiDef.datapoint.criticalityCalculationThresholds = [];
112
+
113
+ switch (kpiDef.datapoint.criticalityCalculationMode) {
114
+ case "UI.ImprovementDirectionType/Target":
115
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue);
116
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue);
117
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue);
118
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue);
119
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue);
120
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue);
121
+ break;
122
+
123
+ case "UI.ImprovementDirectionType/Minimize":
124
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue);
125
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue);
126
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue);
127
+ break;
128
+
129
+ case "UI.ImprovementDirectionType/Maximize":
130
+ default:
131
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue);
132
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue);
133
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue);
134
+ }
135
+ } else {
136
+ kpiDef.datapoint.criticalityValue = MessageType.None;
137
+ }
138
+
139
+ return kpiDef;
140
+ } else {
141
+ var _targetKPI$Detail2;
142
+
143
+ if (!targetKPI) {
144
+ // Couldn't find a KPI with the qualifier specified in the manifest
145
+ converterContext.getDiagnostics().addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_NOT_FOUND + kpiConfig.qualifier);
146
+ } else if (!((_targetKPI$Detail2 = targetKPI.Detail) === null || _targetKPI$Detail2 === void 0 ? void 0 : _targetKPI$Detail2.DefaultPresentationVariant)) {
147
+ // No KPI detail/default presentation variant
148
+ converterContext.getDiagnostics().addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_DETAIL_NOT_FOUND + kpiConfig.qualifier);
149
+ } else {
150
+ // Entity doesn't support analytics
151
+ converterContext.getDiagnostics().addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.NO_ANALYTICS + kpiConfig.entitySet);
152
+ }
153
+
154
+ return undefined;
155
+ }
156
+ }
157
+ /**
158
+ * Creates the KPI definitions from the manifest and the annotations.
159
+ *
160
+ * @param {ConverterContext} converterContext The converter context for the page
161
+ * @returns {KPIDefinition[]} Returns an array of KPI definitions
162
+ */
163
+
164
+
165
+ function getKPIDefinitions(converterContext) {
166
+ var kpiConfigs = converterContext.getManifestWrapper().getKPIConfiguration(),
167
+ kpiDefs = [];
168
+ Object.keys(kpiConfigs).forEach(function (kpiName) {
169
+ var oDef = createKPIDefinition(kpiName, kpiConfigs[kpiName], converterContext);
170
+
171
+ if (oDef) {
172
+ kpiDefs.push(oDef);
173
+ }
174
+ });
175
+ return kpiDefs;
176
+ }
177
+
178
+ _exports.getKPIDefinitions = getKPIDefinitions;
179
+ return _exports;
180
+ }, false);
181
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIktQSS50cyJdLCJuYW1lcyI6WyJjcmVhdGVLUElEZWZpbml0aW9uIiwia3BpTmFtZSIsImtwaUNvbmZpZyIsImNvbnZlcnRlckNvbnRleHQiLCJrcGlDb252ZXJ0ZXJDb250ZXh0IiwiZ2V0Q29udmVydGVyQ29udGV4dEZvciIsImVudGl0eVNldCIsImFLUElBbm5vdGF0aW9ucyIsImdldEFubm90YXRpb25zQnlUZXJtIiwidGFyZ2V0S1BJIiwiZmluZCIsImtwaSIsInF1YWxpZmllciIsImFnZ3JlZ2F0aW9uSGVscGVyIiwiQWdncmVnYXRpb25IZWxwZXIiLCJnZXRFbnRpdHlUeXBlIiwiRGV0YWlsIiwiRGVmYXVsdFByZXNlbnRhdGlvblZhcmlhbnQiLCJpc0FuYWx5dGljc1N1cHBvcnRlZCIsImtwaUlEIiwiS1BJSUQiLCJkYXRhcG9pbnRBbm5vdGF0aW9uIiwiRGF0YVBvaW50IiwiZGF0YXBvaW50UHJvcGVydHkiLCJWYWx1ZSIsIiR0YXJnZXQiLCJpc1Byb3BlcnR5QWdncmVnYXRhYmxlIiwiZ2V0RGlhZ25vc3RpY3MiLCJhZGRJc3N1ZSIsIklzc3VlQ2F0ZWdvcnkiLCJBbm5vdGF0aW9uIiwiSXNzdWVTZXZlcml0eSIsIk1lZGl1bSIsIklzc3VlVHlwZSIsIktQSV9JU1NVRVMiLCJNQUlOX1BST1BFUlRZX05PVF9BR0dSRUdBVEFCTEUiLCJ1bmRlZmluZWQiLCJrcGlEZWYiLCJpZCIsImRhdGFwb2ludCIsInByb3BlcnR5UGF0aCIsInBhdGgiLCJhbm5vdGF0aW9uUGF0aCIsImdldEVudGl0eVNldEJhc2VkQW5ub3RhdGlvblBhdGgiLCJmdWxseVF1YWxpZmllZE5hbWUiLCJzZWxlY3Rpb25WYXJpYW50RmlsdGVyRGVmaW5pdGlvbnMiLCJTZWxlY3Rpb25WYXJpYW50IiwiZ2V0RmlsdGVyRGVmaW5pdGlvbnNGcm9tU2VsZWN0aW9uVmFyaWFudCIsInRhcmdldFZhbHVlUHJvcGVydHkiLCJhbm5vdGF0aW9ucyIsIk1lYXN1cmVzIiwiSVNPQ3VycmVuY3kiLCJjdXJyZW5jeSIsImlzUGF0aEV4cHJlc3Npb24iLCJ1bml0IiwidmFsdWUiLCJuYW1lIiwiaXNDdXJyZW5jeSIsImlzUGF0aCIsInRvU3RyaW5nIiwiVW5pdCIsIkNyaXRpY2FsaXR5IiwiY3JpdGljYWxpdHlQcm9wZXJ0eSIsImNyaXRpY2FsaXR5UGF0aCIsImNyaXRpY2FsaXR5VmFsdWUiLCJNZXNzYWdlVHlwZSIsIk5vbmUiLCJnZXRNZXNzYWdlVHlwZUZyb21Dcml0aWNhbGl0eVR5cGUiLCJDcml0aWNhbGl0eUNhbGN1bGF0aW9uIiwiY3JpdGljYWxpdHlDYWxjdWxhdGlvbk1vZGUiLCJJbXByb3ZlbWVudERpcmVjdGlvbiIsImNyaXRpY2FsaXR5Q2FsY3VsYXRpb25UaHJlc2hvbGRzIiwicHVzaCIsIkRldmlhdGlvblJhbmdlTG93VmFsdWUiLCJUb2xlcmFuY2VSYW5nZUxvd1ZhbHVlIiwiQWNjZXB0YW5jZVJhbmdlTG93VmFsdWUiLCJBY2NlcHRhbmNlUmFuZ2VIaWdoVmFsdWUiLCJUb2xlcmFuY2VSYW5nZUhpZ2hWYWx1ZSIsIkRldmlhdGlvblJhbmdlSGlnaFZhbHVlIiwiS1BJX05PVF9GT1VORCIsIktQSV9ERVRBSUxfTk9UX0ZPVU5EIiwiTk9fQU5BTFlUSUNTIiwiZ2V0S1BJRGVmaW5pdGlvbnMiLCJrcGlDb25maWdzIiwiZ2V0TWFuaWZlc3RXcmFwcGVyIiwiZ2V0S1BJQ29uZmlndXJhdGlvbiIsImtwaURlZnMiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsIm9EZWYiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXNDQSxXQUFTQSxtQkFBVCxDQUE2QkMsT0FBN0IsRUFBOENDLFNBQTlDLEVBQTJFQyxnQkFBM0UsRUFBMEk7QUFBQTs7QUFDekksUUFBTUMsbUJBQW1CLEdBQUdELGdCQUFnQixDQUFDRSxzQkFBakIsQ0FBd0MsTUFBTUgsU0FBUyxDQUFDSSxTQUF4RCxDQUE1QjtBQUNBLFFBQU1DLGVBQWUsR0FBR0gsbUJBQW1CLENBQUNJLG9CQUFwQixDQUF5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Q2QsSUFBUixDQUFha0IsSUFBYjtBQUNBO0FBQ0QsS0FMRDtBQU9BLFdBQU9KLE9BQVA7QUFDQSIsInNvdXJjZVJvb3QiOiIuIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgS1BJQ29uZmlndXJhdGlvbiB9IGZyb20gXCIuLi8uLi9NYW5pZmVzdFNldHRpbmdzXCI7XG5pbXBvcnQgeyBQcm9wZXJ0eSB9IGZyb20gXCJAc2FwLXV4L2Fubm90YXRpb24tY29udmVydGVyXCI7XG5pbXBvcnQge1xuXHRBbm5vdGF0aW9uVGVybSxcblx0VUlBbm5vdGF0aW9uVGVybXMsXG5cdFBhdGhBbm5vdGF0aW9uRXhwcmVzc2lvbixcblx0Q3JpdGljYWxpdHlUeXBlLFxuXHRJbXByb3ZlbWVudERpcmVjdGlvblR5cGVcbn0gZnJvbSBcIkBzYXAtdXgvdm9jYWJ1bGFyaWVzLXR5cGVzXCI7XG5pbXBvcnQgeyBLUElUeXBlIH0gZnJvbSBcIkBzYXAtdXgvdm9jYWJ1bGFyaWVzLXR5cGVzL2Rpc3QvZ2VuZXJhdGVkL1VJXCI7XG5pbXBvcnQgQ29udmVydGVyQ29udGV4dCBmcm9tIFwic2FwL2ZlL2NvcmUvY29udmVydGVycy9Db252ZXJ0ZXJDb250ZXh0XCI7XG5pbXBvcnQgeyBLUElJRCB9IGZyb20gXCIuLi8uLi9oZWxwZXJzL0lEXCI7XG5pbXBvcnQgeyBpc1BhdGhFeHByZXNzaW9uIH0gZnJvbSBcInNhcC9mZS9jb3JlL3RlbXBsYXRpbmcvUHJvcGVydHlIZWxwZXJcIjtcbmltcG9ydCB7IE1lc3NhZ2VUeXBlIH0gZnJvbSBcInNhcC9mZS9jb3JlL2Zvcm1hdHRlcnMvVGFibGVGb3JtYXR0ZXJUeXBlc1wiO1xuaW1wb3J0IHsgQWdncmVnYXRpb25IZWxwZXIgfSBmcm9tIFwiLi4vLi4vaGVscGVycy9BZ2dyZWdhdGlvblwiO1xuaW1wb3J0IHsgSXNzdWVDYXRlZ29yeSwgSXNzdWVTZXZlcml0eSwgSXNzdWVUeXBlIH0gZnJvbSBcInNhcC9mZS9jb3JlL2NvbnZlcnRlcnMvaGVscGVycy9Jc3N1ZU1hbmFnZXJcIjtcbmltcG9ydCB7IGdldE1lc3NhZ2VUeXBlRnJvbUNyaXRpY2FsaXR5VHlwZSB9IGZyb20gXCIuL0NyaXRpY2FsaXR5XCI7XG5pbXBvcnQgeyBnZXRGaWx0ZXJEZWZpbml0aW9uc0Zyb21TZWxlY3Rpb25WYXJpYW50LCBGaWx0ZXJEZWZpbml0aW9uIH0gZnJvbSBcInNhcC9mZS9jb3JlL2NvbnZlcnRlcnMvaGVscGVycy9TZWxlY3Rpb25WYXJpYW50SGVscGVyXCI7XG5cbmV4cG9ydCB0eXBlIEtQSURlZmluaXRpb24gPSB7XG5cdGlkOiBzdHJpbmc7XG5cdGVudGl0eVNldDogc3RyaW5nO1xuXHRkYXRhcG9pbnQ6IHtcblx0XHRhbm5vdGF0aW9uUGF0aDogc3RyaW5nO1xuXHRcdHByb3BlcnR5UGF0aDogc3RyaW5nO1xuXHRcdHVuaXQ/OiB7XG5cdFx0XHR2YWx1ZTogc3RyaW5nO1xuXHRcdFx0aXNQYXRoOiBib29sZWFuO1xuXHRcdFx0aXNDdXJyZW5jeTogYm9vbGVhbjtcblx0XHR9O1xuXHRcdGNyaXRpY2FsaXR5UGF0aD86IHN0cmluZztcblx0XHRjcml0aWNhbGl0eVZhbHVlPzogTWVzc2FnZVR5cGU7XG5cdFx0Y3JpdGljYWxpdHlDYWxjdWxhdGlvbk1vZGU/OiBJbXByb3ZlbWVudERpcmVjdGlvblR5cGU7XG5cdFx0Y3JpdGljYWxpdHlDYWxjdWxhdGlvblRocmVzaG9sZHM/OiAobnVtYmVyIHwgdW5kZWZpbmVkIHwgbnVsbClbXTtcblx0fTtcblx0c2VsZWN0aW9uVmFyaWFudEZpbHRlckRlZmluaXRpb25zPzogRmlsdGVyRGVmaW5pdGlvbltdO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlS1BJRGVmaW5pdGlvbihrcGlOYW1lOiBzdHJpbmcsIGtwaUNvbmZpZzogS1BJQ29uZmlndXJhdGlvbiwgY29udmVydGVyQ29udGV4dDogQ29udmVydGVyQ29udGV4dCk6IEtQSURlZmluaXRpb24gfCB1bmRlZmluZWQge1xuXHRjb25zdCBrcGlDb252ZXJ0ZXJDb250ZXh0ID0gY29udmVydGVyQ29udGV4dC5nZXRDb252ZXJ0ZXJDb250ZXh0Rm9yKFwiL1wiICsga3BpQ29uZmlnLmVudGl0eVNldCk7XG5cdGNvbnN0IGFLUElBbm5vdGF0aW9ucyA9IGtwaUNvbnZlcnRlckNvbnRleHQuZ2V0QW5ub3RhdGlvbnNCeVRlcm0oXCJVSVwiLCBVSUFubm90YXRpb25UZXJtcy5LUEkpIGFzIEFubm90YXRpb25UZXJtPEtQSVR5cGU+W107XG5cdGNvbnN0IHRhcmdldEtQSSA9IGFLUElBbm5vdGF0aW9ucy5maW5kKGtwaSA9PiB7XG5cdFx0cmV0dXJuIGtwaS5xdWFsaWZpZXIgPT09IGtwaUNvbmZpZy5xdWFsaWZpZXI7XG5cdH0pO1xuXHRjb25zdCBhZ2dyZWdhdGlvbkhlbHBlciA9IG5ldyBBZ2dyZWdhdGlvbkhlbHBlcihrcGlDb252ZXJ0ZXJDb250ZXh0LmdldEVudGl0eVR5cGUoKSwga3BpQ29udmVydGVyQ29udGV4dCk7XG5cblx0aWYgKHRhcmdldEtQSSAmJiB0YXJnZXRLUEkuRGV0YWlsPy5EZWZhdWx0UHJlc2VudGF0aW9uVmFyaWFudCAmJiBhZ2dyZWdhdGlvbkhlbHBlci5pc0FuYWx5dGljc1N1cHBvcnRlZCgpKSB7XG5cdFx0Y29uc3Qga3BpSUQgPSBLUElJRChrcGlOYW1lKTtcblxuXHRcdC8vIERhdGFwb2ludFxuXHRcdGNvbnN0IGRhdGFwb2ludEFubm90YXRpb24gPSB0YXJnZXRLUEkuRGF0YVBvaW50O1xuXHRcdGNvbnN0IGRhdGFwb2ludFByb3BlcnR5ID0gZGF0YXBvaW50QW5ub3RhdGlvbi5WYWx1ZS4kdGFyZ2V0IGFzIFByb3BlcnR5O1xuXHRcdGlmICghYWdncmVnYXRpb25IZWxwZXIuaXNQcm9wZXJ0eUFnZ3JlZ2F0YWJsZShkYXRhcG9pbnRQcm9wZXJ0eSkpIHtcblx0XHRcdC8vIFRoZSBtYWluIHByb3BlcnR5IG9mIHRoZSBLUEkgaXMgbm90IGFnZ3JlZ2F0YWJsZSAtLT4gV2UgY2FuJ3QgY2FsY3VsYXRlIGl0cyB2YWx1ZSBzbyB3ZSBpZ25vcmUgdGhlIEtQSVxuXHRcdFx0Y29udmVydGVyQ29udGV4dFxuXHRcdFx0XHQuZ2V0RGlhZ25vc3RpY3MoKVxuXHRcdFx0XHQuYWRkSXNzdWUoXG5cdFx0XHRcdFx0SXNzdWVDYXRlZ29yeS5Bbm5vdGF0aW9uLFxuXHRcdFx0XHRcdElzc3VlU2V2ZXJpdHkuTWVkaXVtLFxuXHRcdFx0XHRcdElzc3VlVHlwZS5LUElfSVNTVUVTLk1BSU5fUFJPUEVSVFlfTk9UX0FHR1JFR0FUQUJMRSArIGtwaUNvbmZpZy5xdWFsaWZpZXJcblx0XHRcdFx0KTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Y29uc3Qga3BpRGVmOiBLUElEZWZpbml0aW9uID0ge1xuXHRcdFx0aWQ6IGtwaUlELFxuXHRcdFx0ZW50aXR5U2V0OiBrcGlDb25maWcuZW50aXR5U2V0LFxuXHRcdFx0ZGF0YXBvaW50OiB7XG5cdFx0XHRcdHByb3BlcnR5UGF0aDogZGF0YXBvaW50QW5ub3RhdGlvbi5WYWx1ZS5wYXRoLFxuXHRcdFx0XHRhbm5vdGF0aW9uUGF0aDoga3BpQ29udmVydGVyQ29udGV4dC5nZXRFbnRpdHlTZXRCYXNlZEFubm90YXRpb25QYXRoKGRhdGFwb2ludEFubm90YXRpb24uZnVsbHlRdWFsaWZpZWROYW1lKVxuXHRcdFx0fSxcblx0XHRcdHNlbGVjdGlvblZhcmlhbnRGaWx0ZXJEZWZpbml0aW9uczogdGFyZ2V0S1BJLlNlbGVjdGlvblZhcmlhbnRcblx0XHRcdFx0PyBnZXRGaWx0ZXJEZWZpbml0aW9uc0Zyb21TZWxlY3Rpb25WYXJpYW50KHRhcmdldEtQSS5TZWxlY3Rpb25WYXJpYW50KVxuXHRcdFx0XHQ6IHVuZGVmaW5lZFxuXHRcdH07XG5cblx0XHQvLyBVbml0IG9yIGN1cnJlbmN5XG5cdFx0Y29uc3QgdGFyZ2V0VmFsdWVQcm9wZXJ0eSA9IGRhdGFwb2ludEFubm90YXRpb24uVmFsdWUuJHRhcmdldCBhcyBQcm9wZXJ0eTtcblx0XHRpZiAodGFyZ2V0VmFsdWVQcm9wZXJ0eS5hbm5vdGF0aW9ucy5NZWFzdXJlcz8uSVNPQ3VycmVuY3kpIHtcblx0XHRcdGNvbnN0IGN1cnJlbmN5ID0gdGFyZ2V0VmFsdWVQcm9wZXJ0eS5hbm5vdGF0aW9ucy5NZWFzdXJlcz8uSVNPQ3VycmVuY3k7XG5cdFx0XHRpZiAoaXNQYXRoRXhwcmVzc2lvbihjdXJyZW5jeSkpIHtcblx0XHRcdFx0a3BpRGVmLmRhdGFwb2ludC51bml0ID0ge1xuXHRcdFx0XHRcdHZhbHVlOiAoKGN1cnJlbmN5LiR0YXJnZXQgYXMgdW5rbm93bikgYXMgUHJvcGVydHkpLm5hbWUsXG5cdFx0XHRcdFx0aXNDdXJyZW5jeTogdHJ1ZSxcblx0XHRcdFx0XHRpc1BhdGg6IHRydWVcblx0XHRcdFx0fTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGtwaURlZi5kYXRhcG9pbnQudW5pdCA9IHtcblx0XHRcdFx0XHR2YWx1ZTogY3VycmVuY3kudG9TdHJpbmcoKSxcblx0XHRcdFx0XHRpc0N1cnJlbmN5OiB0cnVlLFxuXHRcdFx0XHRcdGlzUGF0aDogZmFsc2Vcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKHRhcmdldFZhbHVlUHJvcGVydHkuYW5ub3RhdGlvbnMuTWVhc3VyZXM/LlVuaXQpIHtcblx0XHRcdGNvbnN0IHVuaXQgPSB0YXJnZXRWYWx1ZVByb3BlcnR5LmFubm90YXRpb25zLk1lYXN1cmVzPy5Vbml0O1xuXHRcdFx0aWYgKGlzUGF0aEV4cHJlc3Npb24odW5pdCkpIHtcblx0XHRcdFx0a3BpRGVmLmRhdGFwb2ludC51bml0ID0ge1xuXHRcdFx0XHRcdHZhbHVlOiAoKHVuaXQuJHRhcmdldCBhcyB1bmtub3duKSBhcyBQcm9wZXJ0eSkubmFtZSxcblx0XHRcdFx0XHRpc0N1cnJlbmN5OiBmYWxzZSxcblx0XHRcdFx0XHRpc1BhdGg6IHRydWVcblx0XHRcdFx0fTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGtwaURlZi5kYXRhcG9pbnQudW5pdCA9IHtcblx0XHRcdFx0XHR2YWx1ZTogdW5pdC50b1N0cmluZygpLFxuXHRcdFx0XHRcdGlzQ3VycmVuY3k6IGZhbHNlLFxuXHRcdFx0XHRcdGlzUGF0aDogZmFsc2Vcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDcml0aWNhbGl0eVxuXHRcdGlmIChkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5KSB7XG5cdFx0XHRpZiAodHlwZW9mIGRhdGFwb2ludEFubm90YXRpb24uQ3JpdGljYWxpdHkgPT09IFwib2JqZWN0XCIpIHtcblx0XHRcdFx0Ly8gQ3JpdGljYWxpdHkgaXMgYSBwYXRoIC0tPiBjaGVjayBpZiB0aGUgY29ycmVzcG9uZGluZyBwcm9wZXJ0eSBpcyBhZ2dyZWdhdGFibGVcblx0XHRcdFx0Y29uc3QgY3JpdGljYWxpdHlQcm9wZXJ0eSA9IChkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5IGFzIFBhdGhBbm5vdGF0aW9uRXhwcmVzc2lvbjxDcml0aWNhbGl0eVR5cGU+KVxuXHRcdFx0XHRcdC4kdGFyZ2V0IGFzIFByb3BlcnR5O1xuXHRcdFx0XHRpZiAoYWdncmVnYXRpb25IZWxwZXIuaXNQcm9wZXJ0eUFnZ3JlZ2F0YWJsZShjcml0aWNhbGl0eVByb3BlcnR5KSkge1xuXHRcdFx0XHRcdGtwaURlZi5kYXRhcG9pbnQuY3JpdGljYWxpdHlQYXRoID0gKGRhdGFwb2ludEFubm90YXRpb24uQ3JpdGljYWxpdHkgYXMgUGF0aEFubm90YXRpb25FeHByZXNzaW9uPENyaXRpY2FsaXR5VHlwZT4pLnBhdGg7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly8gVGhlIHByb3BlcnR5IGlzbid0IGFnZ3JlZ2F0YWJsZSAtLT4gd2UgaWdub3JlIGl0XG5cdFx0XHRcdFx0a3BpRGVmLmRhdGFwb2ludC5jcml0aWNhbGl0eVZhbHVlID0gTWVzc2FnZVR5cGUuTm9uZTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gQ3JpdGljYWxpdHkgaXMgYW4gZW51bSBWYWx1ZSAtLT4gZ2V0IHRoZSBjb3JyZXNwb25kaW5nIHN0YXRpYyB2YWx1ZVxuXHRcdFx0XHRrcGlEZWYuZGF0YXBvaW50LmNyaXRpY2FsaXR5VmFsdWUgPSBnZXRNZXNzYWdlVHlwZUZyb21Dcml0aWNhbGl0eVR5cGUoZGF0YXBvaW50QW5ub3RhdGlvbi5Dcml0aWNhbGl0eSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5Q2FsY3VsYXRpb24pIHtcblx0XHRcdGtwaURlZi5kYXRhcG9pbnQuY3JpdGljYWxpdHlDYWxjdWxhdGlvbk1vZGUgPSBkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5Q2FsY3VsYXRpb24uSW1wcm92ZW1lbnREaXJlY3Rpb247XG5cdFx0XHRrcGlEZWYuZGF0YXBvaW50LmNyaXRpY2FsaXR5Q2FsY3VsYXRpb25UaHJlc2hvbGRzID0gW107XG5cdFx0XHRzd2l0Y2ggKGtwaURlZi5kYXRhcG9pbnQuY3JpdGljYWxpdHlDYWxjdWxhdGlvbk1vZGUpIHtcblx0XHRcdFx0Y2FzZSBcIlVJLkltcHJvdmVtZW50RGlyZWN0aW9uVHlwZS9UYXJnZXRcIjpcblx0XHRcdFx0XHRrcGlEZWYuZGF0YXBvaW50LmNyaXRpY2FsaXR5Q2FsY3VsYXRpb25UaHJlc2hvbGRzLnB1c2goXG5cdFx0XHRcdFx0XHRkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5Q2FsY3VsYXRpb24uRGV2aWF0aW9uUmFuZ2VMb3dWYWx1ZVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0a3BpRGVmLmRhdGFwb2ludC5jcml0aWNhbGl0eUNhbGN1bGF0aW9uVGhyZXNob2xkcy5wdXNoKFxuXHRcdFx0XHRcdFx0ZGF0YXBvaW50QW5ub3RhdGlvbi5Dcml0aWNhbGl0eUNhbGN1bGF0aW9uLlRvbGVyYW5jZVJhbmdlTG93VmFsdWVcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdGtwaURlZi5kYXRhcG9pbnQuY3JpdGljYWxpdHlDYWxjdWxhdGlvblRocmVzaG9sZHMucHVzaChcblx0XHRcdFx0XHRcdGRhdGFwb2ludEFubm90YXRpb24uQ3JpdGljYWxpdHlDYWxjdWxhdGlvbi5BY2NlcHRhbmNlUmFuZ2VMb3dWYWx1ZVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0a3BpRGVmLmRhdGFwb2ludC5jcml0aWNhbGl0eUNhbGN1bGF0aW9uVGhyZXNob2xkcy5wdXNoKFxuXHRcdFx0XHRcdFx0ZGF0YXBvaW50QW5ub3RhdGlvbi5Dcml0aWNhbGl0eUNhbGN1bGF0aW9uLkFjY2VwdGFuY2VSYW5nZUhpZ2hWYWx1ZVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0a3BpRGVmLmRhdGFwb2ludC5jcml0aWNhbGl0eUNhbGN1bGF0aW9uVGhyZXNob2xkcy5wdXNoKFxuXHRcdFx0XHRcdFx0ZGF0YXBvaW50QW5ub3RhdGlvbi5Dcml0aWNhbGl0eUNhbGN1bGF0aW9uLlRvbGVyYW5jZVJhbmdlSGlnaFZhbHVlXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRrcGlEZWYuZGF0YXBvaW50LmNyaXRpY2FsaXR5Q2FsY3VsYXRpb25UaHJlc2hvbGRzLnB1c2goXG5cdFx0XHRcdFx0XHRkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5Q2FsY3VsYXRpb24uRGV2aWF0aW9uUmFuZ2VIaWdoVmFsdWVcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdGNhc2UgXCJVSS5JbXByb3ZlbWVudERpcmVjdGlvblR5cGUvTWluaW1pemVcIjpcblx0XHRcdFx0XHRrcGlEZWYuZGF0YXBvaW50LmNyaXRpY2FsaXR5Q2FsY3VsYXRpb25UaHJlc2hvbGRzLnB1c2goXG5cdFx0XHRcdFx0XHRkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5Q2FsY3VsYXRpb24uQWNjZXB0YW5jZVJhbmdlSGlnaFZhbHVlXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRrcGlEZWYuZGF0YXBvaW50LmNyaXRpY2FsaXR5Q2FsY3VsYXRpb25UaHJlc2hvbGRzLnB1c2goXG5cdFx0XHRcdFx0XHRkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5Q2FsY3VsYXRpb24uVG9sZXJhbmNlUmFuZ2VIaWdoVmFsdWVcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdGtwaURlZi5kYXRhcG9pbnQuY3JpdGljYWxpdHlDYWxjdWxhdGlvblRocmVzaG9sZHMucHVzaChcblx0XHRcdFx0XHRcdGRhdGFwb2ludEFubm90YXRpb24uQ3JpdGljYWxpdHlDYWxjdWxhdGlvbi5EZXZpYXRpb25SYW5nZUhpZ2hWYWx1ZVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSBcIlVJLkltcHJvdmVtZW50RGlyZWN0aW9uVHlwZS9NYXhpbWl6ZVwiOlxuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdGtwaURlZi5kYXRhcG9pbnQuY3JpdGljYWxpdHlDYWxjdWxhdGlvblRocmVzaG9sZHMucHVzaChcblx0XHRcdFx0XHRcdGRhdGFwb2ludEFubm90YXRpb24uQ3JpdGljYWxpdHlDYWxjdWxhdGlvbi5EZXZpYXRpb25SYW5nZUxvd1ZhbHVlXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRrcGlEZWYuZGF0YXBvaW50LmNyaXRpY2FsaXR5Q2FsY3VsYXRpb25UaHJlc2hvbGRzLnB1c2goXG5cdFx0XHRcdFx0XHRkYXRhcG9pbnRBbm5vdGF0aW9uLkNyaXRpY2FsaXR5Q2FsY3VsYXRpb24uVG9sZXJhbmNlUmFuZ2VMb3dWYWx1ZVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0a3BpRGVmLmRhdGFwb2ludC5jcml0aWNhbGl0eUNhbGN1bGF0aW9uVGhyZXNob2xkcy5wdXNoKFxuXHRcdFx0XHRcdFx0ZGF0YXBvaW50QW5ub3RhdGlvbi5Dcml0aWNhbGl0eUNhbGN1bGF0aW9uLkFjY2VwdGFuY2VSYW5nZUxvd1ZhbHVlXG5cdFx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0a3BpRGVmLmRhdGFwb2ludC5jcml0aWNhbGl0eVZhbHVlID0gTWVzc2FnZVR5cGUuTm9uZTtcblx0XHR9XG5cblx0XHRyZXR1cm4ga3BpRGVmO1xuXHR9IGVsc2Uge1xuXHRcdGlmICghdGFyZ2V0S1BJKSB7XG5cdFx0XHQvLyBDb3VsZG4ndCBmaW5kIGEgS1BJIHdpdGggdGhlIHF1YWxpZmllciBzcGVjaWZpZWQgaW4gdGhlIG1hbmlmZXN0XG5cdFx0XHRjb252ZXJ0ZXJDb250ZXh0XG5cdFx0XHRcdC5nZXREaWFnbm9zdGljcygpXG5cdFx0XHRcdC5hZGRJc3N1ZShJc3N1ZUNhdGVnb3J5LkFubm90YXRpb24sIElzc3VlU2V2ZXJpdHkuTWVkaXVtLCBJc3N1ZVR5cGUuS1BJX0lTU1VFUy5LUElfTk9UX0ZPVU5EICsga3BpQ29uZmlnLnF1YWxpZmllcik7XG5cdFx0fSBlbHNlIGlmICghdGFyZ2V0S1BJLkRldGFpbD8uRGVmYXVsdFByZXNlbnRhdGlvblZhcmlhbnQpIHtcblx0XHRcdC8vIE5vIEtQSSBkZXRhaWwvZGVmYXVsdCBwcmVzZW50YXRpb24gdmFyaWFudFxuXHRcdFx0Y29udmVydGVyQ29udGV4dFxuXHRcdFx0XHQuZ2V0RGlhZ25vc3RpY3MoKVxuXHRcdFx0XHQuYWRkSXNzdWUoSXNzdWVDYXRlZ29yeS5Bbm5vdGF0aW9uLCBJc3N1ZVNldmVyaXR5Lk1lZGl1bSwgSXNzdWVUeXBlLktQSV9JU1NVRVMuS1BJX0RFVEFJTF9OT1RfRk9VTkQgKyBrcGlDb25maWcucXVhbGlmaWVyKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gRW50aXR5IGRvZXNuJ3Qgc3VwcG9ydCBhbmFseXRpY3Ncblx0XHRcdGNvbnZlcnRlckNvbnRleHRcblx0XHRcdFx0LmdldERpYWdub3N0aWNzKClcblx0XHRcdFx0LmFkZElzc3VlKElzc3VlQ2F0ZWdvcnkuQW5ub3RhdGlvbiwgSXNzdWVTZXZlcml0eS5NZWRpdW0sIElzc3VlVHlwZS5LUElfSVNTVUVTLk5PX0FOQUxZVElDUyArIGtwaUNvbmZpZy5lbnRpdHlTZXQpO1xuXHRcdH1cblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgS1BJIGRlZmluaXRpb25zIGZyb20gdGhlIG1hbmlmZXN0IGFuZCB0aGUgYW5ub3RhdGlvbnMuXG4gKlxuICogQHBhcmFtIHtDb252ZXJ0ZXJDb250ZXh0fSBjb252ZXJ0ZXJDb250ZXh0IFRoZSBjb252ZXJ0ZXIgY29udGV4dCBmb3IgdGhlIHBhZ2VcbiAqIEByZXR1cm5zIHtLUElEZWZpbml0aW9uW119IFJldHVybnMgYW4gYXJyYXkgb2YgS1BJIGRlZmluaXRpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRLUElEZWZpbml0aW9ucyhjb252ZXJ0ZXJDb250ZXh0OiBDb252ZXJ0ZXJDb250ZXh0KTogS1BJRGVmaW5pdGlvbltdIHtcblx0Y29uc3Qga3BpQ29uZmlncyA9IGNvbnZlcnRlckNvbnRleHQuZ2V0TWFuaWZlc3RXcmFwcGVyKCkuZ2V0S1BJQ29uZmlndXJhdGlvbigpLFxuXHRcdGtwaURlZnM6IEtQSURlZmluaXRpb25bXSA9IFtdO1xuXG5cdE9iamVjdC5rZXlzKGtwaUNvbmZpZ3MpLmZvckVhY2goa3BpTmFtZSA9PiB7XG5cdFx0Y29uc3Qgb0RlZiA9IGNyZWF0ZUtQSURlZmluaXRpb24oa3BpTmFtZSwga3BpQ29uZmlnc1trcGlOYW1lXSwgY29udmVydGVyQ29udGV4dCk7XG5cdFx0aWYgKG9EZWYpIHtcblx0XHRcdGtwaURlZnMucHVzaChvRGVmKTtcblx0XHR9XG5cdH0pO1xuXG5cdHJldHVybiBrcGlEZWZzO1xufVxuIl19
@@ -0,0 +1,220 @@
1
+ import { KPIConfiguration } from "../../ManifestSettings";
2
+ import { Property } from "@sap-ux/annotation-converter";
3
+ import {
4
+ AnnotationTerm,
5
+ UIAnnotationTerms,
6
+ PathAnnotationExpression,
7
+ CriticalityType,
8
+ ImprovementDirectionType
9
+ } from "@sap-ux/vocabularies-types";
10
+ import { KPIType } from "@sap-ux/vocabularies-types/dist/generated/UI";
11
+ import ConverterContext from "sap/fe/core/converters/ConverterContext";
12
+ import { KPIID } from "../../helpers/ID";
13
+ import { isPathExpression } from "sap/fe/core/templating/PropertyHelper";
14
+ import { MessageType } from "sap/fe/core/formatters/TableFormatterTypes";
15
+ import { AggregationHelper } from "../../helpers/Aggregation";
16
+ import { IssueCategory, IssueSeverity, IssueType } from "sap/fe/core/converters/helpers/IssueManager";
17
+ import { getMessageTypeFromCriticalityType } from "./Criticality";
18
+ import { getFilterDefinitionsFromSelectionVariant, FilterDefinition } from "sap/fe/core/converters/helpers/SelectionVariantHelper";
19
+
20
+ export type KPIDefinition = {
21
+ id: string;
22
+ entitySet: string;
23
+ datapoint: {
24
+ annotationPath: string;
25
+ propertyPath: string;
26
+ unit?: {
27
+ value: string;
28
+ isPath: boolean;
29
+ isCurrency: boolean;
30
+ };
31
+ criticalityPath?: string;
32
+ criticalityValue?: MessageType;
33
+ criticalityCalculationMode?: ImprovementDirectionType;
34
+ criticalityCalculationThresholds?: (number | undefined | null)[];
35
+ };
36
+ selectionVariantFilterDefinitions?: FilterDefinition[];
37
+ };
38
+
39
+ function createKPIDefinition(kpiName: string, kpiConfig: KPIConfiguration, converterContext: ConverterContext): KPIDefinition | undefined {
40
+ const kpiConverterContext = converterContext.getConverterContextFor("/" + kpiConfig.entitySet);
41
+ const aKPIAnnotations = kpiConverterContext.getAnnotationsByTerm("UI", UIAnnotationTerms.KPI) as AnnotationTerm<KPIType>[];
42
+ const targetKPI = aKPIAnnotations.find(kpi => {
43
+ return kpi.qualifier === kpiConfig.qualifier;
44
+ });
45
+ const aggregationHelper = new AggregationHelper(kpiConverterContext.getEntityType(), kpiConverterContext);
46
+
47
+ if (targetKPI && targetKPI.Detail?.DefaultPresentationVariant && aggregationHelper.isAnalyticsSupported()) {
48
+ const kpiID = KPIID(kpiName);
49
+
50
+ // Datapoint
51
+ const datapointAnnotation = targetKPI.DataPoint;
52
+ const datapointProperty = datapointAnnotation.Value.$target as Property;
53
+ if (!aggregationHelper.isPropertyAggregatable(datapointProperty)) {
54
+ // The main property of the KPI is not aggregatable --> We can't calculate its value so we ignore the KPI
55
+ converterContext
56
+ .getDiagnostics()
57
+ .addIssue(
58
+ IssueCategory.Annotation,
59
+ IssueSeverity.Medium,
60
+ IssueType.KPI_ISSUES.MAIN_PROPERTY_NOT_AGGREGATABLE + kpiConfig.qualifier
61
+ );
62
+ return undefined;
63
+ }
64
+
65
+ const kpiDef: KPIDefinition = {
66
+ id: kpiID,
67
+ entitySet: kpiConfig.entitySet,
68
+ datapoint: {
69
+ propertyPath: datapointAnnotation.Value.path,
70
+ annotationPath: kpiConverterContext.getEntitySetBasedAnnotationPath(datapointAnnotation.fullyQualifiedName)
71
+ },
72
+ selectionVariantFilterDefinitions: targetKPI.SelectionVariant
73
+ ? getFilterDefinitionsFromSelectionVariant(targetKPI.SelectionVariant)
74
+ : undefined
75
+ };
76
+
77
+ // Unit or currency
78
+ const targetValueProperty = datapointAnnotation.Value.$target as Property;
79
+ if (targetValueProperty.annotations.Measures?.ISOCurrency) {
80
+ const currency = targetValueProperty.annotations.Measures?.ISOCurrency;
81
+ if (isPathExpression(currency)) {
82
+ kpiDef.datapoint.unit = {
83
+ value: ((currency.$target as unknown) as Property).name,
84
+ isCurrency: true,
85
+ isPath: true
86
+ };
87
+ } else {
88
+ kpiDef.datapoint.unit = {
89
+ value: currency.toString(),
90
+ isCurrency: true,
91
+ isPath: false
92
+ };
93
+ }
94
+ } else if (targetValueProperty.annotations.Measures?.Unit) {
95
+ const unit = targetValueProperty.annotations.Measures?.Unit;
96
+ if (isPathExpression(unit)) {
97
+ kpiDef.datapoint.unit = {
98
+ value: ((unit.$target as unknown) as Property).name,
99
+ isCurrency: false,
100
+ isPath: true
101
+ };
102
+ } else {
103
+ kpiDef.datapoint.unit = {
104
+ value: unit.toString(),
105
+ isCurrency: false,
106
+ isPath: false
107
+ };
108
+ }
109
+ }
110
+
111
+ // Criticality
112
+ if (datapointAnnotation.Criticality) {
113
+ if (typeof datapointAnnotation.Criticality === "object") {
114
+ // Criticality is a path --> check if the corresponding property is aggregatable
115
+ const criticalityProperty = (datapointAnnotation.Criticality as PathAnnotationExpression<CriticalityType>)
116
+ .$target as Property;
117
+ if (aggregationHelper.isPropertyAggregatable(criticalityProperty)) {
118
+ kpiDef.datapoint.criticalityPath = (datapointAnnotation.Criticality as PathAnnotationExpression<CriticalityType>).path;
119
+ } else {
120
+ // The property isn't aggregatable --> we ignore it
121
+ kpiDef.datapoint.criticalityValue = MessageType.None;
122
+ }
123
+ } else {
124
+ // Criticality is an enum Value --> get the corresponding static value
125
+ kpiDef.datapoint.criticalityValue = getMessageTypeFromCriticalityType(datapointAnnotation.Criticality);
126
+ }
127
+ } else if (datapointAnnotation.CriticalityCalculation) {
128
+ kpiDef.datapoint.criticalityCalculationMode = datapointAnnotation.CriticalityCalculation.ImprovementDirection;
129
+ kpiDef.datapoint.criticalityCalculationThresholds = [];
130
+ switch (kpiDef.datapoint.criticalityCalculationMode) {
131
+ case "UI.ImprovementDirectionType/Target":
132
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
133
+ datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue
134
+ );
135
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
136
+ datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue
137
+ );
138
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
139
+ datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue
140
+ );
141
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
142
+ datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue
143
+ );
144
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
145
+ datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue
146
+ );
147
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
148
+ datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue
149
+ );
150
+ break;
151
+
152
+ case "UI.ImprovementDirectionType/Minimize":
153
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
154
+ datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue
155
+ );
156
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
157
+ datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue
158
+ );
159
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
160
+ datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue
161
+ );
162
+ break;
163
+
164
+ case "UI.ImprovementDirectionType/Maximize":
165
+ default:
166
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
167
+ datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue
168
+ );
169
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
170
+ datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue
171
+ );
172
+ kpiDef.datapoint.criticalityCalculationThresholds.push(
173
+ datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue
174
+ );
175
+ }
176
+ } else {
177
+ kpiDef.datapoint.criticalityValue = MessageType.None;
178
+ }
179
+
180
+ return kpiDef;
181
+ } else {
182
+ if (!targetKPI) {
183
+ // Couldn't find a KPI with the qualifier specified in the manifest
184
+ converterContext
185
+ .getDiagnostics()
186
+ .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_NOT_FOUND + kpiConfig.qualifier);
187
+ } else if (!targetKPI.Detail?.DefaultPresentationVariant) {
188
+ // No KPI detail/default presentation variant
189
+ converterContext
190
+ .getDiagnostics()
191
+ .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_DETAIL_NOT_FOUND + kpiConfig.qualifier);
192
+ } else {
193
+ // Entity doesn't support analytics
194
+ converterContext
195
+ .getDiagnostics()
196
+ .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.NO_ANALYTICS + kpiConfig.entitySet);
197
+ }
198
+ return undefined;
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Creates the KPI definitions from the manifest and the annotations.
204
+ *
205
+ * @param {ConverterContext} converterContext The converter context for the page
206
+ * @returns {KPIDefinition[]} Returns an array of KPI definitions
207
+ */
208
+ export function getKPIDefinitions(converterContext: ConverterContext): KPIDefinition[] {
209
+ const kpiConfigs = converterContext.getManifestWrapper().getKPIConfiguration(),
210
+ kpiDefs: KPIDefinition[] = [];
211
+
212
+ Object.keys(kpiConfigs).forEach(kpiName => {
213
+ const oDef = createKPIDefinition(kpiName, kpiConfigs[kpiName], converterContext);
214
+ if (oDef) {
215
+ kpiDefs.push(oDef);
216
+ }
217
+ });
218
+
219
+ return kpiDefs;
220
+ }