@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,767 @@
1
+ // Copyright (c) 2009-2021 SAP SE. All rights reserved.
2
+
3
+ /* eslint-disable no-console */
4
+
5
+ /**
6
+ * @fileOverview This file contains miscellaneous utility functions.
7
+ */
8
+
9
+
10
+ sap.ui.define([
11
+ "sap/ui/thirdparty/URI",
12
+ "sap/base/Log",
13
+ "sap/ushell_abap/pbServices/ui2/Error"
14
+ ], function (
15
+ URI,
16
+ Log,
17
+ SrvcError
18
+ ) {
19
+ "use strict";
20
+
21
+
22
+
23
+ var Utils = function () { };
24
+
25
+ // ensure that Function.prototype.bind is available, even with iOS 5
26
+ // utils.js is used with startup service, shell API and page building services
27
+ if (!Function.prototype.bind) {
28
+ /**
29
+ * Replacement for ECMAScript 5 feature which might still be missing.
30
+ *
31
+ * @param {object} oThis
32
+ * The value to be passed as the <code>this</code> parameter to the target
33
+ * function when the bound function is called. The value is ignored if the
34
+ * bound function is constructed using the <code>new</code> operator.
35
+ * @param {...object} aVarArgs
36
+ * Arguments to prepend to arguments provided to the bound function when
37
+ * invoking the target function.
38
+ * @returns {function}
39
+ * A function with the bound arguments aVarArgs
40
+ *
41
+ * @see <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind">bind in ECMAScript 5</a>
42
+ */
43
+ Function.prototype.bind = function (oThis) {
44
+ /* eslint-enable no-extend-native */
45
+ if (typeof this !== "function") {
46
+ // closest thing possible to the ECMAScript 5 internal IsCallable function
47
+ throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
48
+ }
49
+
50
+ var aArgs = Array.prototype.slice.call(arguments, 1),
51
+ that = this,
52
+ NOP = function () { /* no-op c'tor */ },
53
+ fBound = function () {
54
+ return that.apply(
55
+ // passing "window" as "this" has been removed (cf. "use strict";)
56
+ this instanceof NOP ? this : oThis,
57
+ aArgs.concat(Array.prototype.slice.call(arguments))
58
+ );
59
+ };
60
+ NOP.prototype = this.prototype;
61
+ fBound.prototype = new NOP();
62
+ return fBound;
63
+ };
64
+ }
65
+
66
+ // cache for GET requests
67
+ var oCache;
68
+
69
+ // "private static" methods **************************************************
70
+
71
+ /**
72
+ * Makes the given relative URL absolute. URLs containing host and/or protocol
73
+ * and URLs with an absolute path remain unchanged. The URL is in no way
74
+ * normalized; the function simply cuts off the file name from the base and
75
+ * appends the relative URL.
76
+ *
77
+ * @param {string} sUrl
78
+ * the (possibly server-relative) URL
79
+ * @param {string} [sBase=location.href]
80
+ * the base URL; it <b>must</b> at least be server-absolute
81
+ * @returns {string}
82
+ * the absolute URL
83
+ * @since 1.2.0
84
+ */
85
+ Utils.absoluteUrl = function (sUrl, sBase) {
86
+ /*jslint regexp: true */
87
+
88
+ // default base is the page location
89
+ sBase = sBase || location.href;
90
+ // base must be absolute
91
+ if (sBase.indexOf("://") < 0 && sBase.charAt(0) !== "/") {
92
+ throw new SrvcError("Illegal base URL: " + sBase);
93
+ }
94
+ // do not change empty or absolute URL
95
+ if (!sUrl || sUrl.indexOf("://") >= 0 || sUrl.charAt(0) === "/") {
96
+ return Utils.addCacheBusterTokenUsingUshellConfig(sUrl);
97
+ }
98
+ if (sBase.search(/^([^:]*:)?\/\/[^/]+$/) < 0) {
99
+ // not a pure server URL -> cut off the file name
100
+ sBase = sBase.replace(/\/[^/]*$/, "");
101
+ }
102
+ // append the relative path
103
+ return Utils.addCacheBusterTokenUsingUshellConfig(sBase + "/" + sUrl);
104
+ };
105
+
106
+ /**
107
+ * Calls the given success handler (a)synchronously. Errors thrown in the success handler are
108
+ * caught and the error message is reported to the error handler; if an error stack is
109
+ * available, it is logged.
110
+ *
111
+ * @param {function ()} fnSuccess
112
+ * no-args success handler
113
+ * @param {function (string)} [fnFailure]
114
+ * error handler, taking an error message; MUST NOT throw any error itself!
115
+ * @param {boolean} [bAsync=false]
116
+ * whether the call shall be asynchronously
117
+ * @since 1.2.0
118
+ */
119
+ Utils.callHandler = function (fnSuccess, fnFailure, bAsync) {
120
+ // see also redundant declaration in sap.ushell.utils.call which has to be in sync
121
+ var sMessage;
122
+
123
+ if (bAsync) {
124
+ setTimeout(function () {
125
+ Utils.callHandler(fnSuccess, fnFailure, false);
126
+ }, 0);
127
+ return;
128
+ }
129
+
130
+ try {
131
+ fnSuccess();
132
+ } catch (e) {
133
+ sMessage = e.message || e.toString();
134
+ Log.error("Call to success handler failed: " + sMessage,
135
+ e.stack);
136
+ if (fnFailure) {
137
+ fnFailure(sMessage);
138
+ }
139
+ }
140
+ };
141
+
142
+ /**
143
+ * GETs the given URL (as XML if indicated) and hands it to the given
144
+ * success handler. As this is a root cause for asynchronous behaviour,
145
+ * special precautions are taken: errors thrown in the success handler are
146
+ * caught and reported to the error handler!
147
+ *
148
+ * @param {string} sUrl
149
+ * URL for GET request
150
+ * @param {boolean} bXml
151
+ * whether the handler expects XML instead of plain text
152
+ * @param {function (*)} fnSuccess
153
+ * success handler, taking a DOM document or text string
154
+ * @param {function (string, string)} fnFailure
155
+ * error handler, taking an error message and (if http status is not OK) the GET response as
156
+ * text; MUST NOT throw any error itself!
157
+ * @param {object} [oXHR]
158
+ * the XMLHttpRequest object which may be predefined (e.g. by setting request headers). If
159
+ * <code>undefined</code>, a new XMLHttpRequest object is created.
160
+ * @param {boolean} [bCache]
161
+ * whether the response is cached for further calls (since 1.8.1). XML responses cannot be
162
+ * cached. An Error is thrown if both <code>bXml</code> and
163
+ * <code>bCache</code> are set to <code>true</code>.
164
+ * @since 1.2.0
165
+ */
166
+ Utils.get = function (sUrl, bXml, fnSuccess, fnFailure, oXHR, bCache) {
167
+ if (typeof fnSuccess !== "function") {
168
+ throw new SrvcError("Missing success handler");
169
+ }
170
+ if (typeof fnFailure !== "function") {
171
+ throw new SrvcError("Missing error handler");
172
+ }
173
+ if (bXml && bCache) {
174
+ throw new SrvcError("Caching of XML responses not supported");
175
+ }
176
+ if (typeof Utils.addCacheBusterTokenUsingUshellConfig === "function") {
177
+ sUrl = Utils.addCacheBusterTokenUsingUshellConfig(sUrl);
178
+ }
179
+ oXHR = oXHR || new XMLHttpRequest();
180
+
181
+ /**
182
+ * @private
183
+ */
184
+ oXHR.onreadystatechange = function () {
185
+ var oResult, oXml;
186
+ // Note: "this" refers to oXHR according to W3C
187
+ if (this.readyState !== /*DONE*/4) {
188
+ return; // not yet DONE
189
+ }
190
+ if (this.status !== /*OK*/200) {
191
+ // HTTP status not OK
192
+ Log.error("Error " + this.status + " in response for URL " + sUrl,
193
+ null);
194
+ fnFailure(sUrl + ": " + this.status + " " + this.statusText, this.responseText);
195
+ return;
196
+ }
197
+
198
+ Log.debug("Received response for URL " + sUrl, null);
199
+ if (bXml) {
200
+ oXml = this.responseXML;
201
+ if (oXml === null || !oXml.documentElement) {
202
+ // in FF it is null, in IE it is a document with only an error message
203
+ fnFailure(sUrl + ": no valid XML");
204
+ return;
205
+ }
206
+ oResult = oXml;
207
+ } else {
208
+ oResult = this.responseText;
209
+ if (bCache) {
210
+ oCache.put(sUrl, oResult);
211
+ }
212
+ }
213
+ Utils.callHandler(fnSuccess.bind(null, oResult), fnFailure);
214
+ };
215
+
216
+ if (!bXml && oCache.containsKey(sUrl)) {
217
+ Log.debug("Return cached response for URL " + sUrl, null);
218
+ Utils.callHandler(fnSuccess.bind(null, oCache.get(sUrl)), fnFailure);
219
+ } else {
220
+ try {
221
+ // Given that the XHR request could be provided as a parameter, we must
222
+ // check that this was not already opened before calling open. One
223
+ // reason this could happen is header settings. Only after opening the
224
+ // request headers can be set. Calling open again will cause the
225
+ // previous request to be aborted (i.e., headers loss).
226
+ if (oXHR.readyState < XMLHttpRequest.OPENED) { // keep working on the opened request
227
+ oXHR.open("GET", sUrl, /*asynchronously*/true);
228
+ } else {
229
+ Log.debug("XHR Request was already opened for " + sUrl, null);
230
+ }
231
+ oXHR.send();
232
+ Log.debug("Sent request to URL " + sUrl, null);
233
+ } catch (e) {
234
+ Log.error("Error '" + (e.message || e) + "' in request to URL " + sUrl,
235
+ null);
236
+ throw e;
237
+ }
238
+ }
239
+ };
240
+
241
+ /**
242
+ * Gets an URL and adds the given cache buster token to it if no other token is already
243
+ * contained. In case the URL is no valid URL the token is not added.
244
+ *
245
+ * @param {string} sUrl
246
+ * e.g. "/sap/bc/ui5_ui5/application/path"
247
+ * URL to be changed
248
+ * @param {regEx} oPattern
249
+ * e.g /^\/sap\/bc\/ui5_ui5\//
250
+ * RegExp to determine if sUrl matches and needs to be extended by the cache buster token
251
+ * sToken
252
+ * @param {string} sReplacement
253
+ * e.g. "/sap/bc/ui5_ui5/[CacheBusterToken]/"
254
+ * The part of sUrl matched by oPattern will be exchanged by this. Before that is done sToken
255
+ * is inserted in sReplacement at the position indicated by [CacheBusterToken]
256
+ * The replacement may refer to capture groups of oPattern
257
+ * @param {string} sToken
258
+ * e.g. "~201412132350000~"
259
+ * token to be inserted in sUrl. It will be inserted as indicated in the final constructed URL!
260
+ * @returns {string}
261
+ * - if sUrl did not matched oPattern: unchanged sUrl
262
+ * - if sUrl matched oPattern: sUrl enhanced with sToken,
263
+ * e.g. "/sap/bc/ui5_ui5/~201412132350000~/application/path"
264
+ *
265
+ * @private
266
+ */
267
+ Utils.addCacheBusterToken = function (sUrl, oPattern, sReplacement, sToken) {
268
+ if (oPattern.test(sUrl)) { //url matches the pattern
269
+ sUrl = sUrl.replace(oPattern, sReplacement);
270
+ //replace the token placeholder globally in the final url (!)
271
+ // (also allow the token to be added elsewhere)
272
+ sUrl = sUrl.replace(/\[CacheBusterToken\]/g, sToken);
273
+ }
274
+ return sUrl;
275
+ };
276
+
277
+ /**
278
+ * Removes a cache buster token (if available) of an Url and normalizes the url afterwards
279
+ * @param {string} sUrl
280
+ * the URL to be normalized
281
+ * @returns {string}
282
+ * normalized url (without a cache buster token)
283
+ * @since 1.28.1
284
+ *
285
+ * @private
286
+ */
287
+ Utils.removeCBAndNormalizeUrl = function (sUrl) {
288
+ var aMatches,
289
+ sUrlPrefix,
290
+ sCacheBusterSegment,
291
+ sUrlPostfix;
292
+
293
+ if (typeof sUrl !== "string" || sUrl === "" || isUriWithRelativeOrEmptyPath(sUrl)) {
294
+ return sUrl;
295
+ }
296
+
297
+ function isUriWithRelativeOrEmptyPath (sUrl0) {
298
+ var oUri = new URI(sUrl0),
299
+ sPath = oUri.path();
300
+
301
+ if (oUri.is("absolute")) {
302
+ return false;
303
+ }
304
+
305
+ if (sPath && sPath.charAt(0) === "/") {
306
+ return false;
307
+ }
308
+
309
+ return true;
310
+ }
311
+
312
+ // split up the URL into 3 parts: prefix, cache-buster segment, postfix
313
+ // leading slashes are always part of the segment, the postfix might have a trailing slash
314
+ aMatches = sUrl.match(/(.*)(\/~[\w-]+~[A-Z0-9]?)(.*)/);
315
+ if (aMatches) {
316
+ sUrlPrefix = aMatches[1];
317
+ sCacheBusterSegment = aMatches[2];
318
+ sUrlPostfix = aMatches[3];
319
+ }
320
+
321
+ function normalizePath (sUrl0) {
322
+ return new URI(sUrl0).normalizePathname().toString();
323
+ }
324
+
325
+ function isRelativePathWithDotSegmentsThatGoOutside (sPath) {
326
+ var aSegments = new URI(sPath).segment(),
327
+ i,
328
+ iPos = 0;
329
+
330
+ for (i = 0; i < aSegments.length && iPos >= 0; i += 1) {
331
+ if (aSegments[i] === "..") {
332
+ iPos = iPos - 1;
333
+ } else {
334
+ iPos = iPos + 1;
335
+ }
336
+ }
337
+
338
+ return iPos < 0;
339
+ }
340
+
341
+ // check if URL contains a cache-buster token
342
+ if (sCacheBusterSegment) {
343
+ // check if removal of cache-buster token is required
344
+ if (sUrlPostfix && isRelativePathWithDotSegmentsThatGoOutside(sUrlPostfix)) {
345
+ // remove the cache-buster token
346
+ sUrl = sUrlPrefix + sUrlPostfix;
347
+ }
348
+ }
349
+
350
+ // always normalize the URL path
351
+ return normalizePath(sUrl);
352
+ };
353
+
354
+ /**
355
+ * Gets an URL and adds the given cache buster token to it if no other token is already
356
+ * contained. The rules to be applied are coming from the ushell configuration:
357
+ * sap-ushell-config.cacheBusting.patterns
358
+ * The rules are applied by there order property (lowest first) and the modified URL is returned
359
+ * as soon as the first rule matched.
360
+ * <p>
361
+ * If the query parameter <code>sap-ushell-nocb</code> is set to <code>true</code> or <code>X</code>,
362
+ * no cache buster tokens are added and existing cache buster tokens are removed from the specified URL.
363
+ *
364
+ * @param {string} sUrl
365
+ * e.g. "/sap/bc/ui5_ui5/application/path"
366
+ * URL to be changed
367
+ * @returns {string}
368
+ * - if sUrl already contained a cache buster token (e.g. ~00000~): unchanged sUrl
369
+ * - if sUrl did not match any pattern: unchanged sUrl
370
+ * - if sUrl matched pattern: sUrl enhanced with sToken,
371
+ * e.g. "/sap/bc/ui5_ui5/~201412132350000~/application/path"
372
+ * - if the modified sUrl (normalized and cache buster token was removed)
373
+ * is found as an attribute of the config
374
+ * (window["sap-ushell-config"].cacheBusting.urls),
375
+ * the cache buster token which is defined as the value of this attribute
376
+ * is going to be returned.
377
+ *
378
+ * @private
379
+ */
380
+ Utils.addCacheBusterTokenUsingUshellConfig = function (sUrl) {
381
+ //TODO move to sap.ushell.utils
382
+ var oCacheBusting = window["sap-ushell-config"] &&
383
+ window["sap-ushell-config"].cacheBusting,
384
+ oPatterns = oCacheBusting && oCacheBusting.patterns,
385
+ sCacheBusterUrl = sUrl,
386
+ aParameterMap = [],
387
+ sSapUshellNoCb,
388
+ aRules = [];
389
+
390
+ aParameterMap = Utils.getParameterMap();
391
+ sSapUshellNoCb = aParameterMap["sap-ushell-nocb"] && aParameterMap["sap-ushell-nocb"][0];
392
+
393
+ // When URL disables Cache Busting return URL without cache busting token
394
+ // It can happen that we get a URL which already has a cache-buster token included (from the ABAP server), so we also remove
395
+ // an existing token here (this implementation is simpler than passing the URL parameter to the resolveLink service and evaluate it there)
396
+ if ((sSapUshellNoCb === "true" || sSapUshellNoCb === "X") && typeof sUrl === "string") {
397
+ sUrl = sUrl.replace(/\/~[\w-]+~[A-Z0-9]?/, "");
398
+ return sUrl;
399
+ }
400
+
401
+ // don't continue if the string is empty or a token is already present,
402
+ // either as path segment (e.g.: /~0123_-Abc~/) or as query parameter
403
+ // /e.g. ?cb=~xxxxxx~
404
+ // also consider URLs with query parameters and fragments
405
+ // this case happens during navigation, because this method is both called from
406
+ // NavTargetResolution service as well as from the stubbed jQuery.sap.registerModulePath method
407
+ //
408
+ // syntax for application cache-buster contains now an additional scope qualifier that can be
409
+ // either empty, "R" for resource, "5" for UI5 app, "W" for web app and "C" for custom
410
+ // see ABAP class /UI5/CL_UI5_APP_HTTP_HANDLER for details
411
+ if (!oCacheBusting
412
+ || typeof sUrl !== "string"
413
+ || sUrl === ""
414
+ || /[/=]~[\w-]+~[A-Z0-9]?[/#?&]/.test(sUrl) // matches intermediate segment with cb-token; consider URLs with query string or fragment
415
+ || /[/=]~[\w-]+~[A-Z0-9]?$/.test(sUrl)) { // matches last segment with cb-token (no trailing slash or further parameters)
416
+ return sUrl;
417
+ }
418
+
419
+ if (oCacheBusting && oCacheBusting.urls) {
420
+ // Removing the last slash of the input url
421
+ if (sUrl.charAt(sUrl.length - 1) === "/") {
422
+ sUrl = sUrl.substr(0, sUrl.length - 1);
423
+ }
424
+ // Config contains the modified url (without a slash at the end)
425
+ if (oCacheBusting.urls.hasOwnProperty(sUrl)) {
426
+ return sUrl + "/" + oCacheBusting.urls[sUrl].cacheBusterToken;
427
+ }
428
+ // Config contains the modified url (having a slash at the end)
429
+ if (oCacheBusting.urls.hasOwnProperty(sUrl + "/")) {
430
+ return sUrl + "/" + oCacheBusting.urls[sUrl + "/"].cacheBusterToken;
431
+ }
432
+ }
433
+
434
+ if (!oPatterns) {
435
+ return sUrl;
436
+ }
437
+
438
+ // put rules in aRules and sort them by oRule.order
439
+ Object.keys(oPatterns).forEach(function (sPattern) {
440
+ if (oPatterns.hasOwnProperty(sPattern)) {
441
+ var oRule = oPatterns[sPattern];
442
+ // the property name is the pattern to be used, copy it to the object itself for later
443
+ oRule.pattern = new RegExp(sPattern);
444
+ aRules.push(oRule);
445
+ }
446
+ });
447
+ aRules.sort(function (oRule1, oRule2) { return oRule1.order - oRule2.order; });
448
+
449
+ // apply rules
450
+ aRules.every(function (oRule) { // use every to be able to break
451
+ if (oRule.pattern.test(sUrl)) {
452
+ if (!oRule.cacheBusterToken) {
453
+ oRule.cacheBusterToken = oCacheBusting.cacheBusterToken;
454
+ }
455
+
456
+ //url matches the pattern, note that this is not redundant
457
+ //one can define patterns without a replacement to match and end the matching process!
458
+ sCacheBusterUrl = Utils.addCacheBusterToken(sUrl, oRule.pattern, oRule.replacement,
459
+ oRule.cacheBusterToken);
460
+ // break as soon as first rule matches (irrespective of alteration)
461
+ return false;
462
+ }
463
+ return true;
464
+ });
465
+
466
+ return sCacheBusterUrl;
467
+ };
468
+
469
+ /**
470
+ * Clear cache for GET requests.
471
+ *
472
+ * @since 1.8.1
473
+ */
474
+ Utils.clearCache = function () {
475
+ oCache = new Utils.Map();
476
+ };
477
+
478
+ /**
479
+ * Gets the device's form factor. Based on <code>sap.ui.Device.system</code> from SAPUI5.
480
+ * @returns {string}
481
+ * the device's form factor ("desktop", "tablet" or "phone")
482
+ * @since 1.19.1
483
+ */
484
+ Utils.getFormFactor = function () {
485
+ // see also redundant declaration in sap.ushell.utils.getFormFactor which has to be in sync
486
+ var oSystem = sap.ui.Device.system;
487
+
488
+ if (oSystem.desktop) {
489
+ return oSystem.SYSTEMTYPE.DESKTOP;
490
+ }
491
+ if (oSystem.tablet) {
492
+ return oSystem.SYSTEMTYPE.TABLET;
493
+ }
494
+ if (oSystem.phone) {
495
+ return oSystem.SYSTEMTYPE.PHONE;
496
+ }
497
+ // returns undefined
498
+ };
499
+
500
+ /**
501
+ * Returns a map of all search parameters present in the given search string
502
+ * or this window's current URL. To be precise, <code>location.search</code>
503
+ * is used as a default and any given search string must use the same syntax
504
+ * (start with a "?" and not include a "#").
505
+ *
506
+ * @param {string} [sSearchString=location.search]
507
+ * search string starting with a "?" (unless empty) and not including a "#"
508
+ * @returns {object}
509
+ * a <code>map&lt;string, string[]></code> from key to array of values
510
+ * @since 1.2.0
511
+ *
512
+ * @see <a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletRequest.html#getParameterMap()">
513
+ * javax.servlet.ServletRequest#getParameterMap()</a>
514
+ * @see <a href="https://sapui5.hana.ondemand.com/sdk/docs/api/symbols/jQuery.sap.util.UriParameters.html">
515
+ * Interface jQuery.sap.util.UriParameters</a>
516
+ */
517
+ Utils.getParameterMap = function (sSearchString) {
518
+ var i,
519
+ n,
520
+ mResult = {},
521
+ sKey,
522
+ sValue,
523
+ iIndexOfEquals,
524
+ aKeyValuePairs,
525
+ // Note: location.search starts with "?" if not empty
526
+ sSearch = arguments.length > 0 ? sSearchString : location.search;
527
+
528
+ if (sSearch && sSearch.charAt(0) !== "?") {
529
+ throw new SrvcError("Illegal search string " + sSearch);
530
+ }
531
+ if (!sSearch || sSearch === "?") {
532
+ return {}; // Note: split("") would return [""]
533
+ }
534
+
535
+ // Note: W3C recommends that servers support ";" as well as "&"
536
+ // (http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.2.2)
537
+ // http://unixpapa.com/js/querystring.html advocates this on the client-side also!
538
+ aKeyValuePairs = sSearch.substring(1).replace(/\+/g, " ").split(/[&;]/);
539
+
540
+ for (i = 0, n = aKeyValuePairs.length; i < n; i += 1) {
541
+ // decode key/value pair at first "=" character
542
+ sKey = aKeyValuePairs[i];
543
+ sValue = ""; // Note: empty value may be omitted altogether
544
+ iIndexOfEquals = sKey.indexOf("=");
545
+ if (iIndexOfEquals >= 0) {
546
+ sValue = sKey.slice(iIndexOfEquals + 1);
547
+ sValue = decodeURIComponent(sValue);
548
+ sKey = sKey.slice(0, iIndexOfEquals);
549
+ }
550
+ sKey = decodeURIComponent(sKey);
551
+
552
+ // map key to value(s)
553
+ // Note: beware of inherited functions!
554
+ if (!Object.prototype.hasOwnProperty.call(mResult, sKey)) {
555
+ mResult[sKey] = [];
556
+ }
557
+ mResult[sKey].push(sValue);
558
+ }
559
+
560
+ return mResult;
561
+ };
562
+
563
+ /**
564
+ * Returns the value of the given URL's GET parameter with the given name, properly decoded.
565
+ * Returns "" if no such parameter can be found.
566
+ *
567
+ * @param {string} sUrl
568
+ * any URL
569
+ * @param {string} sName
570
+ * the name of the GET parameter we are looking for
571
+ * @returns {string}
572
+ * the parameter value, properly decoded
573
+ *
574
+ * @private
575
+ * @since 1.17.0
576
+ */
577
+ Utils.getParameterValue = function (sUrl, sName) {
578
+ var oParameterMap, iQueryIndex;
579
+
580
+ if (typeof sName !== "string") {
581
+ // avoid surprises when sName would later be converted into a string
582
+ throw new SrvcError("Missing parameter name");
583
+ }
584
+
585
+ sUrl = sUrl.split("#")[0];
586
+ iQueryIndex = sUrl.indexOf("?");
587
+ if (iQueryIndex >= 0) {
588
+ oParameterMap = Utils.getParameterMap(sUrl.slice(iQueryIndex));
589
+ if (oParameterMap[sName]) {
590
+ return oParameterMap[sName][0];
591
+ }
592
+ }
593
+ return "";
594
+ };
595
+
596
+ /**
597
+ * Tells whether the given value is an array.
598
+ *
599
+ * @param {object} o
600
+ * any value
601
+ * @returns {boolean}
602
+ * <code>true</code> if and only if the given value is an array
603
+ * @since 1.2.0
604
+ */
605
+ Utils.isArray = function (o) {
606
+ // see Crockford page 61
607
+ return Object.prototype.toString.apply(o) === "[object Array]";
608
+ };
609
+ /**
610
+ * Tells whether the given value is a string.
611
+ *
612
+ * @param {object} o
613
+ * any value
614
+ * @returns {boolean}
615
+ * <code>true</code> if and only if the given value is a string
616
+ * @since 1.50.1
617
+ */
618
+ Utils.isString = function name (o) {
619
+ return /String/.test(Object.prototype.toString.call(o));
620
+ };
621
+
622
+ /**
623
+ * Parses the given XML string and returns it as a document.
624
+ *
625
+ * @param {string} sXml
626
+ * the XML
627
+ * @returns {DOMDocument}
628
+ * a DOM document, or <code>null</code> in case of missing or empty XML string
629
+ * @throws {Error}
630
+ * in case of invalid XML string
631
+ * @since 1.2.0
632
+ */
633
+ Utils.parseXml = function (sXml) {
634
+ var oXml;
635
+ if (!sXml || typeof sXml !== "string") {
636
+ return null;
637
+ }
638
+ oXml = new DOMParser().parseFromString(sXml, "text/xml");
639
+ if (oXml.getElementsByTagName("parsererror").length) { // Chrome, Firefox
640
+ throw new SrvcError("Invalid XML: " + sXml);
641
+ }
642
+ return oXml;
643
+ };
644
+
645
+ /**
646
+ * Serves as a marker for functions that are to be exposed in QUnit tests. Calls to this function
647
+ * are expected to be placed directly before the named function declaration (even <b>after</b>
648
+ * the JSDoc). The function itself does nothing.
649
+ *
650
+ * @param {object} o
651
+ * the object to which this function will be attached in tests; must not be <code>this</code>
652
+ * (use <code>that</code> instead)
653
+ * @since 1.3.0
654
+ */
655
+
656
+ // "public classes" **********************************************************
657
+
658
+ /**
659
+ * Creates an empty map. It is used for mapping from arbitrary string(!) keys (including "get" or
660
+ * "hasOwnProperty") to values of any type.
661
+ * @class
662
+ * @since 1.5.0
663
+ */
664
+ Utils.Map = function () {
665
+ this.entries = {};
666
+ };
667
+
668
+ /**
669
+ * Associates the specified value with the specified key in this map. If the map previously
670
+ * contained a mapping for the key, the old value is replaced by the specified value. Returns
671
+ * the old value. Note: It might be a good idea to assert that the old value is
672
+ * <code>undefined</code> in case you expect your keys to be unique.
673
+ *
674
+ * @param {string} sKey
675
+ * key with which the specified value is to be associated
676
+ * @param {any} vValue
677
+ * value to be associated with the specified key
678
+ * @returns {any}
679
+ * the old value
680
+ * @since 1.5.0
681
+ */
682
+ Utils.Map.prototype.put = function (sKey, vValue) {
683
+ var vOldValue = this.get(sKey);
684
+ this.entries[sKey] = vValue;
685
+ return vOldValue;
686
+ };
687
+
688
+ /**
689
+ * Returns <tt>true</tt> if this map contains a mapping for the specified key.
690
+ *
691
+ * @param {string} sKey
692
+ * key whose presence in this map is to be tested
693
+ * @returns {boolean}
694
+ * <tt>true</tt> if this map contains a mapping for the specified key
695
+ * @since 1.5.0
696
+ */
697
+ Utils.Map.prototype.containsKey = function (sKey) {
698
+ if (typeof sKey !== "string") {
699
+ throw new SrvcError("Not a string key: " + sKey);
700
+ }
701
+ return Object.prototype.hasOwnProperty.call(this.entries, sKey);
702
+ };
703
+
704
+ /**
705
+ * Returns the value to which the specified key is mapped, or <code>undefined</code> if this map
706
+ * contains no mapping for the key.
707
+ * @param {string} sKey
708
+ * the key whose associated value is to be returned
709
+ * @returns {any}
710
+ * the value to which the specified key is mapped, or <code>undefined</code> if this map
711
+ * contains no mapping for the key
712
+ * @since 1.5.0
713
+ */
714
+ Utils.Map.prototype.get = function (sKey) {
715
+ if (this.containsKey(sKey)) {
716
+ return this.entries[sKey];
717
+ }
718
+ return undefined;
719
+ };
720
+
721
+ /**
722
+ * Returns an array of this map's keys. This array is a snapshot of the map; concurrent
723
+ * modifications of the map while iterating do not influence the sequence.
724
+ * @returns {string[]}
725
+ * this map's keys
726
+ * @since 1.5.0
727
+ */
728
+ Utils.Map.prototype.keys = function () {
729
+ return Object.keys(this.entries);
730
+ };
731
+
732
+ /**
733
+ * Removes a key together with its value from the map.
734
+ * @param {string} sKey
735
+ * the map's key to be removed
736
+ * @since 1.11.0
737
+ */
738
+ Utils.Map.prototype.remove = function (sKey) {
739
+ delete this.entries[sKey];
740
+ };
741
+
742
+ /**
743
+ * Returns this map's string representation.
744
+ *
745
+ * @returns {string}
746
+ * this map's string representation
747
+ * @since 1.5.0
748
+ */
749
+ Utils.Map.prototype.toString = function () {
750
+ var aResult = ["Map("];
751
+ aResult.push(JSON.stringify(this.entries));
752
+ aResult.push(")");
753
+ return aResult.join("");
754
+ };
755
+
756
+ // initialize the cache for GET
757
+ Utils.clearCache();
758
+
759
+
760
+ // TODO remove when FLPD is adapted (uses this function in global namespace)
761
+ sap.ui2 = sap.ui2 || {};
762
+ sap.ui2.srvc = sap.ui2.srvc || {};
763
+ sap.ui2.srvc.removeCBAndNormalizeUrl = Utils.removeCBAndNormalizeUrl;
764
+ sap.ui2.srvc.addCacheBusterTokenUsingUshellConfig = Utils.addCacheBusterTokenUsingUshellConfig;
765
+
766
+ return Utils;
767
+ });