@sapui5/sap.ushell_abap 1.94.0 → 1.96.1

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 (115) hide show
  1. package/package.json +1 -1
  2. package/src/main/js/sap/ui2/srvc/ODataWrapper.js +1 -1
  3. package/src/main/js/sap/ushell_abap/.library +4 -9
  4. package/src/main/js/sap/ushell_abap/adapters/abap/AdapterContainer.js +12 -5
  5. package/src/main/js/sap/ushell_abap/adapters/abap/AppStateAdapter.js +11 -7
  6. package/src/main/js/sap/ushell_abap/adapters/abap/ClientSideTargetResolutionAdapter.js +47 -32
  7. package/src/main/js/sap/ushell_abap/adapters/abap/ConfigurationDefaultsAdapter.js +1 -1
  8. package/src/main/js/sap/ushell_abap/adapters/abap/ContainerAdapter.js +46 -38
  9. package/src/main/js/sap/ushell_abap/adapters/abap/LaunchPageAdapter.js +438 -398
  10. package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionAdapter.js +1 -1
  11. package/src/main/js/sap/ushell_abap/adapters/abap/PageBuildingAdapter.js +25 -15
  12. package/src/main/js/sap/ushell_abap/adapters/abap/PagePersistenceAdapter.js +3 -2
  13. package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationAdapter.js +16 -7
  14. package/src/main/js/sap/ushell_abap/adapters/abap/SearchAdapter.js +1 -1
  15. package/src/main/js/sap/ushell_abap/adapters/abap/SupportTicketAdapter.js +8 -8
  16. package/src/main/js/sap/ushell_abap/adapters/abap/Ui5ComponentLoaderAdapter.js +1 -1
  17. package/src/main/js/sap/ushell_abap/adapters/abap/UserInfoAdapter.js +11 -4
  18. package/src/main/js/sap/ushell_abap/adapters/hana/ContainerAdapter.js +9 -3
  19. package/src/main/js/sap/ushell_abap/bootstrap/evo/XhrLogonEventHandler.js +13 -11
  20. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap-def-dev.js +1 -1
  21. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap-def.js +1 -1
  22. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.bootstrap.utils.js +8 -4
  23. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.configure.ushell.js +1 -1
  24. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.constants.js +9 -0
  25. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.get.server.config.Urls.js +12 -5
  26. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.load.launchpad.js +21 -22
  27. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.pageset.js +8 -2
  28. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.server.config.js +6 -3
  29. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.startup.js +10 -5
  30. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.ui5.boot.handler.js +7 -4
  31. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.xhr.handler.js +10 -3
  32. package/src/main/js/sap/ushell_abap/bootstrap/evo/boottask.js +21 -16
  33. package/src/main/js/sap/ushell_abap/library.js +2 -2
  34. package/src/main/js/sap/ushell_abap/pbServices/ui2/AllCatalogs.js +186 -0
  35. package/src/main/js/sap/ushell_abap/pbServices/ui2/Bag.js +704 -0
  36. package/src/main/js/sap/ushell_abap/pbServices/ui2/Catalog.js +930 -0
  37. package/src/main/js/sap/ushell_abap/pbServices/ui2/Chip.js +1027 -0
  38. package/src/main/js/sap/ushell_abap/pbServices/ui2/ChipDefinition.js +216 -0
  39. package/src/main/js/sap/ushell_abap/pbServices/ui2/ChipInstance.js +933 -0
  40. package/src/main/js/sap/ushell_abap/pbServices/ui2/Error.js +45 -0
  41. package/src/main/js/sap/ushell_abap/pbServices/ui2/Factory.js +647 -0
  42. package/src/main/js/sap/ushell_abap/pbServices/ui2/ODataService.js +251 -0
  43. package/src/main/js/sap/ushell_abap/pbServices/ui2/ODataWrapper.js +1262 -0
  44. package/src/main/js/sap/ushell_abap/pbServices/ui2/Page.js +920 -0
  45. package/src/main/js/sap/ushell_abap/pbServices/ui2/PageBuildingService.js +1498 -0
  46. package/src/main/js/sap/ushell_abap/pbServices/ui2/PageSet.js +466 -0
  47. package/src/main/js/sap/ushell_abap/pbServices/ui2/RemoteCatalogService.js +52 -0
  48. package/src/main/js/sap/ushell_abap/pbServices/ui2/Utils.js +767 -0
  49. package/src/main/js/sap/ushell_abap/pbServices/ui2/chipdefinition.xsd +139 -0
  50. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/actions.js +244 -0
  51. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/bag.js +150 -0
  52. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/configuration.js +165 -0
  53. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/configurationUi.js +330 -0
  54. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/fullscreen.js +70 -0
  55. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/navigation.js +50 -0
  56. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/preview.js +289 -0
  57. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/refresh.js +43 -0
  58. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/search.js +115 -0
  59. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/types.js +9 -0
  60. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/url.js +105 -0
  61. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/visible.js +128 -0
  62. package/ui5.yaml +30 -0
  63. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/Component.js +0 -426
  64. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/css/style.css +0 -1
  65. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n.properties +0 -56
  66. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_ar.properties +0 -36
  67. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_bg.properties +0 -36
  68. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_ca.properties +0 -36
  69. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_cs.properties +0 -36
  70. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_cy.properties +0 -36
  71. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_da.properties +0 -36
  72. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_de.properties +0 -36
  73. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_el.properties +0 -36
  74. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_en.properties +0 -36
  75. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_en_GB.properties +0 -36
  76. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_en_US_sappsd.properties +0 -36
  77. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_en_US_saprigi.properties +0 -36
  78. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_en_US_saptrc.properties +0 -36
  79. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_es.properties +0 -36
  80. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_es_MX.properties +0 -36
  81. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_et.properties +0 -36
  82. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_fi.properties +0 -36
  83. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_fr.properties +0 -36
  84. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_fr_CA.properties +0 -36
  85. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_hi.properties +0 -36
  86. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_hr.properties +0 -36
  87. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_hu.properties +0 -36
  88. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_id.properties +0 -36
  89. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_it.properties +0 -36
  90. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_iw.properties +0 -36
  91. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_ja.properties +0 -36
  92. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_kk.properties +0 -36
  93. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_ko.properties +0 -36
  94. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_lt.properties +0 -36
  95. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_lv.properties +0 -36
  96. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_ms.properties +0 -36
  97. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_nl.properties +0 -36
  98. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_no.properties +0 -36
  99. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_pl.properties +0 -36
  100. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_pt.properties +0 -36
  101. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_pt_PT.properties +0 -36
  102. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_ro.properties +0 -36
  103. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_ru.properties +0 -36
  104. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_sh.properties +0 -36
  105. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_sk.properties +0 -36
  106. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_sl.properties +0 -36
  107. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_sv.properties +0 -36
  108. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_th.properties +0 -36
  109. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_tr.properties +0 -36
  110. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_uk.properties +0 -36
  111. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_vi.properties +0 -36
  112. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_zh_CN.properties +0 -36
  113. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/i18n/i18n_zh_TW.properties +0 -36
  114. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/manifest.json +0 -153
  115. package/src/main/js/sap/ushell_abap/plugins/fcc-transport-ui/model/models.js +0 -14
@@ -0,0 +1,704 @@
1
+ // Copyright (c) 2009-2021 SAP SE. All rights reserved.
2
+
3
+ /**
4
+ * @fileOverview A wrapper for a property bag loaded from the page building service.
5
+ */
6
+
7
+ sap.ui.define([
8
+ "sap/ushell_abap/pbServices/ui2/Utils",
9
+ "sap/ushell_abap/pbServices/ui2/Error",
10
+ "sap/base/Log"
11
+ ], function (
12
+ Utils,
13
+ SrvcError,
14
+ Log
15
+ ) {
16
+ "use strict";
17
+
18
+ // "public class" ************************************************************
19
+
20
+ /**
21
+ * Constructs a new representation (wrapper) of the bag with the given
22
+ * bag description as loaded from the given factory's page building service.
23
+ * A property bag can be associated with a page (see {@link sap.ushell_abap.pbServices.ui2.Page#getBag}), a
24
+ * CHIP instance (see {@link sap.ushell_abap.pbServices.ui2.ChipInstance#getBag}) or a CHIP
25
+ * (see {@link sap.ushell_abap.pbServices.ui2.Chip#getBag}). Such bags take arbitrary name/value pairs consisting
26
+ * of strings.
27
+ *
28
+ * @param {sap.ushell_abap.pbServices.ui2.Factory} oFactory
29
+ * the factory
30
+ * @param {object} oAlterEgo
31
+ * the bag data including its (optional) properties as loaded via the page building service
32
+ * @param {object} [oParentBag]
33
+ * a bag which is asked for properties not found in this bag
34
+ * @param {function(sap.ushell_abap.pbServices.ui2.Bag)} [fnChangeListener]
35
+ * (since 1.21) a listener to be called (with this bag as an argument) each time this bag
36
+ * changes due to save or reset; the listener is not called in case a backend request fails
37
+ * completely
38
+ *
39
+ * @class
40
+ * @since 1.3.0
41
+ */
42
+ var Bag = function (oFactory, oAlterEgo, oParentBag, fnChangeListener) {
43
+ var oPropertiesByName,
44
+ bResetting = false,
45
+ bSaving = false,
46
+ that = this;
47
+
48
+ // BEWARE: constructor code below!
49
+
50
+ // "private" methods ---------------------------------------------------------
51
+
52
+ /**
53
+ * Throws an error if the bag is currently running a <code>reset</code>.
54
+ *
55
+ * @private
56
+ */
57
+ function errorIfResetRunning () {
58
+ if (bResetting) {
59
+ throw new SrvcError("The previous reset operation is not finished yet",
60
+ "Bag");
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Throws an error if the bag is currently running a <code>save</code>.
66
+ *
67
+ * @private
68
+ */
69
+ function errorIfSaveRunning () {
70
+ if (bSaving) {
71
+ throw new SrvcError("The previous save operation is not finished yet",
72
+ "Bag");
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Fills the <code>oPropertiesByName</code> map based on the properties in the given bag data,
78
+ * updating only the given accepted names if applicable.
79
+ *
80
+ * @param {object} oBagData
81
+ * parsed JSON object as returned by the OData service representing this bag
82
+ * @param {Utils.Map} [oAcceptedNames]
83
+ * map (used as a "hash set") of accepted names; if missing, all are accepted
84
+ * @private
85
+ */
86
+ function fillPropertyMap (oBagData, oAcceptedNames) {
87
+ var aProperties = (oBagData.Properties && oBagData.Properties.results)
88
+ || (oBagData.ChipInstanceProperties && oBagData.ChipInstanceProperties.results)
89
+ || (oBagData.ChipProperties && oBagData.ChipProperties.results)
90
+ || [];
91
+
92
+ oPropertiesByName = oPropertiesByName || new Utils.Map();
93
+ aProperties.forEach(function (oPropertyData) {
94
+ var sName = oPropertyData.name,
95
+ oOldProperty;
96
+
97
+ if (!oAcceptedNames || oAcceptedNames.containsKey(sName)) {
98
+ oOldProperty = oPropertiesByName.put(sName, oPropertyData);
99
+ oPropertyData.$currentValue = oOldProperty
100
+ ? oOldProperty.$currentValue // keep current value
101
+ : oPropertyData.value;
102
+ }
103
+ });
104
+
105
+ // remove relations
106
+ delete oBagData.ChipInstanceProperties;
107
+ delete oBagData.ChipProperties;
108
+ delete oBagData.Properties;
109
+ }
110
+
111
+ /**
112
+ * Returns the names of all translatable or non-translatable properties (as indicated) of
113
+ * this bag, taking the given names from the parent bag into account. Avoids duplicates.
114
+ *
115
+ * @param {string[]} aNames
116
+ * names from parent bag or <code>[]</code>
117
+ * @param {boolean} bTranslatable
118
+ * whether names of translatable text properties are requested
119
+ * @returns {string[]}
120
+ * an array containing all names
121
+ * @private
122
+ */
123
+ function getNames (aNames, bTranslatable) {
124
+ var oNameSet;
125
+
126
+ if (aNames.length === 0) { // no parent names --> no duplicates expected, run faster code
127
+ oPropertiesByName.keys().forEach(function (sKey) {
128
+ if (bTranslatable === (oPropertiesByName.get(sKey).translatable === "X")) {
129
+ aNames.push(sKey);
130
+ }
131
+ });
132
+ return aNames;
133
+ }
134
+
135
+ // parent names present --> expect duplicates and avoid them with slower code
136
+ oNameSet = new Utils.Map();
137
+ aNames.forEach(function (sKey) {
138
+ oNameSet.put(sKey);
139
+ });
140
+ oPropertiesByName.keys().forEach(function (sKey) {
141
+ if (bTranslatable === (oPropertiesByName.get(sKey).translatable === "X")) {
142
+ oNameSet.put(sKey);
143
+ }
144
+ });
145
+ return oNameSet.keys();
146
+ }
147
+
148
+ /**
149
+ * Returns a mock of a parent page or CHIP instance which contains the exact IDs and nothing
150
+ * else.
151
+ * @returns {object} a mock of a parent page or CHIP instance
152
+ *
153
+ * @private
154
+ */
155
+ function getParentMock () {
156
+ // Note: bags at Chip level are read-only and can be ignored here!
157
+ if (oAlterEgo.instanceId) {
158
+ return { pageId: oAlterEgo.pageId, instanceId: oAlterEgo.instanceId };
159
+ }
160
+ return { id: oAlterEgo.pageId };
161
+ }
162
+
163
+ /**
164
+ * Sets the value for the given property name. If no such property exists yet, it will be
165
+ * created. If <code>setProperty()</code> is called during a running {@link #save()}, the
166
+ * property will <i>not</i> be saved immediately. It will only be saved with the next call to
167
+ * {@link #save()}.
168
+ *
169
+ * @param {string} sPropertyName
170
+ * the property name (which has to be a string)
171
+ * @param {string} sValue
172
+ * the value (which has to be a string)
173
+ * @param {boolean} bTranslatable
174
+ * whether this property is a translatable text property
175
+ * @returns {sap.ushell_abap.pbServices.ui2.Bag}
176
+ * this bag
177
+ * @throws Error when called while {@link #reset()} is running.
178
+ * @private
179
+ */
180
+ function setProperty (sPropertyName, sValue, bTranslatable) {
181
+ var oProperty;
182
+
183
+ if (!sPropertyName) {
184
+ throw new SrvcError("Property name must not be empty", "sap.ushell_abap.pbServices.ui2.Bag");
185
+ }
186
+ if (typeof sPropertyName !== "string") {
187
+ throw new SrvcError("Property name must be a string", "sap.ushell_abap.pbServices.ui2.Bag");
188
+ }
189
+ oProperty = oPropertiesByName.get(sPropertyName);
190
+ if (oProperty && ((oProperty.translatable === "X") !== bTranslatable)) {
191
+ throw new SrvcError(
192
+ "'" + sPropertyName + "' already exists as a "
193
+ + (bTranslatable ? "non-translatable" : "translatable text")
194
+ + " property",
195
+ "sap.ushell_abap.pbServices.ui2.Bag"
196
+ );
197
+ }
198
+ if (typeof sValue !== "string") {
199
+ throw new SrvcError("Property value must be a string", "sap.ushell_abap.pbServices.ui2.Bag");
200
+ }
201
+ errorIfResetRunning();
202
+
203
+ if (!oProperty) {
204
+ oProperty = { name: sPropertyName, translatable: (bTranslatable ? "X" : " ") };
205
+ oPropertiesByName.put(sPropertyName, oProperty);
206
+ }
207
+ oProperty.$currentValue = sValue;
208
+ return that;
209
+ }
210
+
211
+ // "public" methods ----------------------------------------------------------
212
+
213
+ /**
214
+ * Returns this bag's ID.
215
+ *
216
+ * @returns {string}
217
+ * this bag's ID
218
+ * @since 1.3.0
219
+ */
220
+ this.getId = function () {
221
+ return oAlterEgo.id;
222
+ };
223
+
224
+ /**
225
+ * Returns an array containing the names of the (non-translatable) properties contained in this
226
+ * bag. In contrast to {@link #getPropertyNames()} the properties of the parent bag are ignored.
227
+ * As long as a {@link #reset()} is running,
228
+ * the "old" property names are returned.
229
+ *
230
+ * If {@link #resetProperty()} has been called on a not persisted property its name is not
231
+ * contained in the array; for a persisted property it is contained in the array until
232
+ * {@link #save()} is called on this bag.
233
+ *
234
+ * @returns {string[]}
235
+ * array of (non-translatable) property names really stored in this bag (not the parent bag)
236
+ *
237
+ * @see #getOwnTextNames
238
+ * @see #getPropertyNames
239
+ * @private
240
+ */
241
+ this.getOwnPropertyNames = function () {
242
+ return getNames([], false);
243
+ };
244
+
245
+ /**
246
+ * Returns an array containing the names of the translatable text properties contained in this
247
+ * bag. In contrast to {@link #getTextNames()} the text properties of the parent bag are
248
+ * ignored. As long as a {@link #reset()} is running, the "old" property names are returned.
249
+ * For an array of non-translatable property names see {@link #getPropertyNames}.
250
+ *
251
+ * @returns {string[]}
252
+ * array of translatable text property names really stored in this bag (not the parent bag)
253
+ *
254
+ * @see #getOwnPropertyNames
255
+ * @see #getTextNames
256
+ * @private
257
+ */
258
+ this.getOwnTextNames = function () {
259
+ return getNames([], true);
260
+ };
261
+
262
+ /**
263
+ * Returns the property value for the given property name. If no such property exists, the
264
+ * given default value is returned.
265
+ * As long as a {@link #reset()} is running, "old" values are returned.
266
+ *
267
+ * @param {string} sPropertyName
268
+ * the property name
269
+ * @param {string} [sDefaultValue]
270
+ * default value used if there is no property with given name
271
+ *
272
+ * @returns {string}
273
+ * the property value
274
+ * @throws Error if <code>sPropertyName</code> is a translatable text property name.
275
+ * @since 1.3.0
276
+ */
277
+ this.getProperty = function (sPropertyName, sDefaultValue) {
278
+ var oProperty = oPropertiesByName.get(sPropertyName);
279
+
280
+ if (oProperty && (oProperty.translatable === "X")) {
281
+ throw new SrvcError("'" + sPropertyName + "' is a translatable text property",
282
+ "sap.ushell_abap.pbServices.ui2.Bag");
283
+ }
284
+
285
+ if (oProperty) {
286
+ return oProperty.$currentValue;
287
+ }
288
+ if (oParentBag) {
289
+ return oParentBag.getProperty(sPropertyName, sDefaultValue);
290
+ }
291
+ return sDefaultValue;
292
+ };
293
+
294
+ /**
295
+ * Returns an array containing the names of the (non-translatable) properties contained in this
296
+ * bag. As long as a {@link #reset()} is running, the "old" property names are returned.
297
+ * For an array of translatable text property names see {@link #getTextNames}.
298
+ *
299
+ * If {@link #resetProperty()} has been called on a not persisted property its name is not
300
+ * contained in the array; for a persisted property it is contained in the array until
301
+ * {@link #save()} is called on this bag.
302
+ *
303
+ * @returns {string[]}
304
+ * array of (non-translatable) property names
305
+ * @since 1.3.0
306
+ *
307
+ * @see #getTextNames
308
+ */
309
+ this.getPropertyNames = function () {
310
+ var aPropertyNames = oParentBag ? oParentBag.getPropertyNames() : [];
311
+
312
+ return getNames(aPropertyNames, false);
313
+ };
314
+
315
+ /**
316
+ * Returns the translatable text for the given text property name. If no such text property
317
+ * exists, <code>sTextName</code> is returned again. As long as a {@link #reset()} is running,
318
+ * "old" texts are returned.
319
+ *
320
+ * @param {string} sTextName
321
+ * the text property name
322
+ * @returns {string}
323
+ * the translatable text
324
+ * @throws Error if <code>sTextName</code> is an ordinary (non-translatable) property name.
325
+ * @since 1.17.1
326
+ */
327
+ this.getText = function (sTextName) {
328
+ var oProperty = oPropertiesByName.get(sTextName);
329
+
330
+ if (oProperty && (oProperty.translatable !== "X")) {
331
+ throw new SrvcError(
332
+ "'" + sTextName + "' is a non-translatable property",
333
+ "sap.ushell_abap.pbServices.ui2.Bag"
334
+ );
335
+ }
336
+
337
+ if (oProperty) {
338
+ return oProperty.$currentValue;
339
+ }
340
+ if (oParentBag) {
341
+ return oParentBag.getText(sTextName);
342
+ }
343
+ return sTextName;
344
+ };
345
+
346
+ /**
347
+ * Returns an array containing the names of the translatable text properties contained in this
348
+ * bag. As long as a {@link #reset()} is running, the "old" property names are returned.
349
+ * For an array of non-translatable property names see {@link #getPropertyNames}.
350
+ *
351
+ * @returns {string[]}
352
+ * array of translatable text property names
353
+ * @since 1.17.1
354
+ *
355
+ * @see #getPropertyNames
356
+ */
357
+ this.getTextNames = function () {
358
+ var aTextNames = oParentBag ? oParentBag.getTextNames() : [];
359
+
360
+ return getNames(aTextNames, true);
361
+ };
362
+
363
+ /**
364
+ * Discards all modified properties, deletes this bag with all its properties and reloads the
365
+ * bag via the factory given in the constructor. If the factory's page building service offers
366
+ * different layers (like <code>sap.ushell_abap.pbServices.ui2.PageBuildingService</code>, calling them
367
+ * <i>scopes</i>), the values from a lower layer will become visible.
368
+ * <p>
369
+ * This is an asynchronous operation. If the bag is reset successfully, the success
370
+ * handler is called. If there is an error while resetting the bag, all old values are kept
371
+ * and the error handler is called.
372
+ *
373
+ * @param {function ()} fnSuccess
374
+ * no-args success handler
375
+ * @param {function (string, object=)} [fnError]
376
+ * error handler taking an error message and, since version 1.28.6, an
377
+ * optional object containing the complete error information as delivered
378
+ * by the ODataService. See fnFailure parameter of {@link sap.ushell_abap.pbServices.ui2.ODataWrapper#onError}
379
+ * for more details.
380
+ * If fnError is not given, the default error handler from the factory's
381
+ * page building service is called.
382
+ * @throws Error when called while {@link #save()} or a previous <code>reset()</code> is
383
+ * running.
384
+ * @since 1.3.0
385
+ */
386
+ this.reset = function (fnSuccess, fnError) {
387
+ var oParent = getParentMock(),
388
+ oPbs = oFactory.getPageBuildingService();
389
+
390
+ function onReadSuccess (oBagData) {
391
+ bResetting = false;
392
+
393
+ oAlterEgo = oBagData;
394
+ oPropertiesByName = undefined;
395
+ fillPropertyMap(oAlterEgo);
396
+ if (fnChangeListener) {
397
+ fnChangeListener(that);
398
+ }
399
+ fnSuccess();
400
+ }
401
+
402
+ if (typeof fnSuccess !== "function") {
403
+ throw new SrvcError("Missing success handler", "sap.ushell_abap.pbServices.ui2.Bag");
404
+ }
405
+
406
+ errorIfSaveRunning();
407
+ errorIfResetRunning();
408
+ bResetting = true;
409
+ fnError = fnError || oPbs.getDefaultErrorHandler();
410
+
411
+ if (oAlterEgo.$tmp) {
412
+ // if bag is not yet persisted do not call delete and read
413
+ Utils.callHandler(onReadSuccess.bind(null, oAlterEgo), fnError, true);
414
+ return;
415
+ }
416
+
417
+ oPbs.deleteBag(oParent, oAlterEgo.id, function () {
418
+ oAlterEgo.$tmp = true;
419
+ // if bag cannot be read because there is no bag in lower layer success handler has to be
420
+ // called; oAlterEgo is passed because success handler expects oData parameter and
421
+ // oAlterEgo contains required information for the bag (like page and name) and no
422
+ // properties (have been deleted after property map has been filled) --> property map
423
+ // is cleared in success handler and we get an empty bag
424
+ oPbs.readBag(oParent, oAlterEgo.id, onReadSuccess, onReadSuccess.bind(null, oAlterEgo));
425
+ }, function () {
426
+ // deleteBag failed
427
+ bResetting = false;
428
+
429
+ // NOTE: call error handler with any arguments passed in this wrapper
430
+ fnError.apply(null, arguments);
431
+ });
432
+ };
433
+
434
+ /**
435
+ * Deletes the property with the given name, no matter if it is translatable or not. If no such
436
+ * property exists, nothing happens.
437
+ * <p>
438
+ * Otherwise, the property value is considered to be <code>undefined</code> until a
439
+ * {@link #save} operation has succeeded. Note how this <code>undefined</code> value is treated
440
+ * differently by {@link #getProperty} and {@link #getText}!
441
+ * <p>
442
+ * <b>BEWARE:</b> This transient <code>undefined</code> value can be wrong due to a number of
443
+ * reasons, including different layers of storage (like
444
+ * <code>sap.ushell_abap.pbServices.ui2.PageBuildingService</code>, calling them <i>scopes</i>) or parent bags
445
+ * (in case of catalog pages), which cannot be taken properly into account until the next time
446
+ * a {@link #save} operation succeeds!
447
+ * <p>
448
+ * After a successful {@link #save} operation, a deleted property may reappear from a lower
449
+ * layer of storage or from a parent bag. If you need to overwrite such values, use
450
+ * {@link #setProperty} instead!
451
+ * <p>
452
+ * If <code>resetProperty()</code> is called during a running {@link #save}, the
453
+ * property will <i>not</i> be saved immediately. It will only be saved with the next call to
454
+ * {@link #save}.
455
+ *
456
+ * @param {string} sPropertyName
457
+ * the property name (which has to be a string)
458
+ * @returns {sap.ushell_abap.pbServices.ui2.Bag}
459
+ * this bag
460
+ * @throws Error when called while {@link #reset} is running.
461
+ *
462
+ * @since 1.17.1
463
+ */
464
+ this.resetProperty = function (sPropertyName) {
465
+ var oProperty;
466
+
467
+ oProperty = oPropertiesByName.get(sPropertyName);
468
+ if (oProperty) {
469
+ oProperty.$currentValue = undefined; //undefined value is marker to delete property on save
470
+ if (!Object.prototype.hasOwnProperty.call(oProperty, "value")) { // no persisted value
471
+ oPropertiesByName.remove(sPropertyName);
472
+ }
473
+ }
474
+ return this;
475
+ };
476
+
477
+ /**
478
+ * Saves this bag with all modified properties. This is an asynchronous operation.
479
+ * If all modified properties have been saved, the success handler is called. If one or more
480
+ * properties cannot be saved, the error handler is called. This error handler reports which
481
+ * properties could not be saved and the corresponding error messages. The properties remain
482
+ * valid and the bag tries to save them again with the next call to <code>save()</code>.
483
+ *
484
+ * <p>
485
+ * If <code>save()</code> is called when there is no modified property, the function calls the
486
+ * success handler asynchronously without any further activity.
487
+ *
488
+ * @param {function ()} fnSuccess
489
+ * no-args success handler. Errors thrown in this function will be reported to the page
490
+ * building service's default error handler (not to <code>fnError</code> since the signature
491
+ * does not fit)
492
+ * @param {function (map<string, string>, map<string, object>)} fnError
493
+ * error handler taking two maps, each mapping individual property names
494
+ * to error message and complete error information respectively. Since
495
+ * version 1.28.6, the second parameter is always returned,
496
+ * but a property name in that object may map to
497
+ * undefined values in case an error object containing the complete error
498
+ * information is not available.<br />
499
+ * For more details about the structure of the error information object
500
+ * see {@link sap.ushell_abap.pbServices.ui2.ODataWrapper#onError}
501
+ * @throws Error when called while {@link #reset()} or a previous <code>save()</code> is
502
+ * running.
503
+ * @since 1.3.0
504
+ */
505
+ this.save = function (fnSuccess, fnError) {
506
+ var iNumberOfRequests = 0,
507
+ oResetPropertyNames = new Utils.Map(), // used as a "hash set"
508
+ mMessagesByName = {},
509
+ mErrorResponseByName = {},
510
+ oParentMock = getParentMock(),
511
+ oPbs = oFactory.getPageBuildingService();
512
+
513
+ if (typeof fnSuccess !== "function") {
514
+ throw new SrvcError("Missing success handler", "sap.ushell_abap.pbServices.ui2.Bag");
515
+ }
516
+ if (typeof fnError !== "function") {
517
+ throw new SrvcError("Missing error handler", "sap.ushell_abap.pbServices.ui2.Bag");
518
+ }
519
+ errorIfSaveRunning();
520
+ errorIfResetRunning();
521
+
522
+ oPbs.openBatchQueue();
523
+
524
+ oPropertiesByName.keys().forEach(function (sName) {
525
+ var oUpdatedProperty,
526
+ oProperty = oPropertiesByName.get(sName);
527
+
528
+ function onError (sMessage, oErrorInformation) {
529
+ mMessagesByName[sName] = sMessage;
530
+ mErrorResponseByName[sName] = oErrorInformation;
531
+ }
532
+
533
+ if (oProperty.$currentValue !== oProperty.value) {
534
+ iNumberOfRequests += 1;
535
+ if (Object.prototype.hasOwnProperty.call(oProperty, "value")) {
536
+ if (oProperty.$currentValue === undefined) {
537
+ // reset property: delete it and re-read bag below
538
+ oResetPropertyNames.put(sName);
539
+ oPbs.deleteProperty(oProperty,
540
+ function () {
541
+ if (oProperty.$currentValue === undefined) { // not re-created via API
542
+ oPropertiesByName.remove(sName);
543
+ } else {
544
+ delete oProperty.value; // not persisted anymore
545
+ }
546
+ }, onError);
547
+ } else {
548
+ // changed property: update it
549
+ oUpdatedProperty = JSON.parse(JSON.stringify(oProperty));
550
+ oUpdatedProperty.value = oProperty.$currentValue; // 1st update clone
551
+ oPbs.updateProperty(oUpdatedProperty,
552
+ function () {
553
+ oProperty.value = oUpdatedProperty.value; // on success, update original
554
+ }, onError);
555
+ }
556
+ } else {
557
+ // new property: create it
558
+ oPbs.createProperty(oParentMock, oAlterEgo.id, sName,
559
+ oProperty.$currentValue, oProperty.translatable,
560
+ function (oNewProperty) {
561
+ // save alter ego because of __metadata needed for later updates
562
+ oNewProperty.$currentValue = oProperty.$currentValue; // keep current value
563
+ oPropertiesByName.put(sName, oNewProperty);
564
+ }, onError);
565
+ }
566
+ }
567
+ });
568
+
569
+ if (oResetPropertyNames.keys().length) {
570
+ // some properties were reset: re-read bag
571
+ oPbs.readBag(oParentMock, oAlterEgo.id, function (oBagData) {
572
+ fillPropertyMap(oBagData, oResetPropertyNames);
573
+ }); // omit error handler, default one must be used here!
574
+ }
575
+
576
+ bSaving = true;
577
+ oPbs.submitBatchQueue(function () {
578
+ bSaving = false;
579
+ if (fnChangeListener && iNumberOfRequests > Object.keys(mMessagesByName).length) {
580
+ // at least one request must succeed
581
+ fnChangeListener(that);
582
+ }
583
+ if (Object.keys(mMessagesByName).length > 0) {
584
+ fnError(mMessagesByName, mErrorResponseByName);
585
+ } else {
586
+ oAlterEgo.$tmp = false;
587
+ fnSuccess(); // Note: try/catch done by submitBatchQueue()!
588
+ }
589
+ });
590
+ };
591
+
592
+ /**
593
+ * Sets the value for the given property name. If no such property exists yet, it will be
594
+ * created. If <code>setProperty()</code> is called during a running {@link #save()}, the
595
+ * property will <i>not</i> be saved immediately. It will only be saved with the next call to
596
+ * {@link #save()}.
597
+ *
598
+ * @param {string} sPropertyName
599
+ * the property name (which has to be a string)
600
+ * @param {string} sValue
601
+ * the value (which has to be a string)
602
+ * @returns {sap.ushell_abap.pbServices.ui2.Bag}
603
+ * this bag
604
+ * @throws Error when called while {@link #reset()} is running.
605
+ * @throws Error when called with a property name which is not of type string or the empty
606
+ * string
607
+ * @since 1.3.0
608
+ */
609
+ this.setProperty = function (sPropertyName, sValue) {
610
+ return setProperty(sPropertyName, sValue, false);
611
+ };
612
+
613
+ /**
614
+ * Sets the translatable text for the given text property name. If no such text property exists
615
+ * yet, it will be created as a translatable text property. Ordinary properties and
616
+ * translatable text properties share a common namespace! Once a property has been created,
617
+ * it is either translatable or not and this cannot be changed by the corresponding setters.
618
+ * You can only call <code>reset()</code> and start all over.
619
+ * <p>
620
+ * Note: You can create or modify translatable text properties only if the session language is
621
+ * the same as the page's original language (see
622
+ * {@link sap.ushell_abap.pbServices.ui2.Page#getOriginalLanguage}).
623
+ * Also note that handling of translatable texts depends on the layer used. In some layers the
624
+ * original language is important; in others it does not matter. In the latter case the empty
625
+ * string (<code>""</code>) is returned, which indicates that the user is allowed to edit the
626
+ * translatable texts in any language.
627
+ * <p>
628
+ * If <code>setText()</code> is called during a running {@link #save()}, the text property will
629
+ * <i>not</i> be saved immediately. It will only be saved with the next call to {@link #save()}.
630
+ *
631
+ * @param {string} sTextName
632
+ * the text property name (must not be empty)
633
+ * @param {string} sText
634
+ * the translatable text (may be empty)
635
+ * @returns {sap.ushell_abap.pbServices.ui2.Bag}
636
+ * this bag
637
+ * @throws Error when called while {@link #reset()} is running or if an ordinary
638
+ * (non-translatable) property with the same name already exists.
639
+ * @since 1.17.1
640
+ *
641
+ * @see sap.ushell_abap.pbServices.ui2.Page#getOriginalLanguage
642
+ * @see chip.bag.getOriginalLanguage
643
+ */
644
+ this.setText = function (sTextName, sText) {
645
+ return setProperty(sTextName, sText, true);
646
+ };
647
+
648
+ /**
649
+ * Returns this bag's string representation.
650
+ *
651
+ * @param {boolean} [bVerbose=false]
652
+ * whether to show all properties
653
+ * @returns {string}
654
+ * this bag's string representation
655
+ * @since 1.3.0
656
+ */
657
+ this.toString = function (bVerbose) {
658
+ var aResult = ['Bag({id:"', oAlterEgo.id,
659
+ '",pageId:"', oAlterEgo.pageId
660
+ ];
661
+ if (oAlterEgo.instanceId) {
662
+ aResult.push('",instanceId:"', oAlterEgo.instanceId);
663
+ }
664
+ aResult.push('"');
665
+ if (bVerbose) {
666
+ aResult.push(",oAlterEgo:", JSON.stringify(oAlterEgo));
667
+ aResult.push(",oPropertiesByName:", oPropertiesByName.toString());
668
+ aResult.push(",bResetting:", bResetting);
669
+ aResult.push(",bSaving:", bSaving);
670
+ }
671
+ aResult.push("})");
672
+ return aResult.join("");
673
+ };
674
+
675
+ /**
676
+ * Replace all properties in this bag with given raw bag data.
677
+ *
678
+ * @param {object} oBagData
679
+ * parsed JSON object as returned by the OData service representing this bag
680
+ * @throws Error when called with bag data which does not fit to this bag.
681
+ * @private
682
+ */
683
+ this.update = function (oBagData) {
684
+ if (!oBagData || oAlterEgo.id !== oBagData.id) {
685
+ throw new SrvcError("Bag data belongs to another bag",
686
+ "sap.ushell_abap.pbServices.ui2.Bag");
687
+ }
688
+ oPropertiesByName = undefined;
689
+ fillPropertyMap(oBagData);
690
+ };
691
+
692
+ // constructor code -------------------------------------------------------
693
+
694
+ fillPropertyMap(oAlterEgo);
695
+ Log.debug("Created: " + this, null, "sap.ushell_abap.pbServices.ui2.Bag");
696
+ };
697
+
698
+ // TODO remove when FLPD is adapted (uses this function in global namespace)
699
+ sap.ui2 = sap.ui2 || {};
700
+ sap.ui2.srvc = sap.ui2.srvc || {};
701
+ sap.ui2.srvc.bag = Bag;
702
+
703
+ return Bag;
704
+ }, true);