@openui5/sap.ui.core 1.102.1 → 1.103.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 (299) hide show
  1. package/package.json +1 -1
  2. package/src/jquery.sap.global.js +2 -2
  3. package/src/jquery.sap.properties.js +1 -1
  4. package/src/jquery.sap.resources.js +1 -1
  5. package/src/jquery.sap.script.js +1 -1
  6. package/src/jquery.sap.storage.js +3 -3
  7. package/src/sap/base/i18n/ResourceBundle.js +2 -2
  8. package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
  9. package/src/sap/base/util/restricted/_castArray.js +1 -1
  10. package/src/sap/base/util/restricted/_compact.js +1 -1
  11. package/src/sap/base/util/restricted/_curry.js +1 -1
  12. package/src/sap/base/util/restricted/_debounce.js +1 -1
  13. package/src/sap/base/util/restricted/_difference.js +1 -1
  14. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  15. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  16. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  17. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  18. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  19. package/src/sap/base/util/restricted/_flatten.js +1 -1
  20. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  21. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  22. package/src/sap/base/util/restricted/_intersection.js +1 -1
  23. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  24. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  25. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  26. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  27. package/src/sap/base/util/restricted/_isNil.js +1 -1
  28. package/src/sap/base/util/restricted/_max.js +1 -1
  29. package/src/sap/base/util/restricted/_merge.js +1 -1
  30. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  31. package/src/sap/base/util/restricted/_min.js +1 -1
  32. package/src/sap/base/util/restricted/_omit.js +1 -1
  33. package/src/sap/base/util/restricted/_pick.js +1 -1
  34. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  35. package/src/sap/base/util/restricted/_throttle.js +1 -1
  36. package/src/sap/base/util/restricted/_toArray.js +1 -1
  37. package/src/sap/base/util/restricted/_union.js +1 -1
  38. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  39. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  40. package/src/sap/base/util/restricted/_uniq.js +1 -1
  41. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  42. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  43. package/src/sap/base/util/restricted/_without.js +1 -1
  44. package/src/sap/base/util/restricted/_xor.js +1 -1
  45. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  46. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  47. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  48. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  49. package/src/sap/ui/Device.js +9 -3
  50. package/src/sap/ui/Global.js +4 -4
  51. package/src/sap/ui/VersionInfo.js +12 -6
  52. package/src/sap/ui/base/Event.js +1 -1
  53. package/src/sap/ui/base/EventProvider.js +2 -2
  54. package/src/sap/ui/base/ExpressionParser.js +2 -2
  55. package/src/sap/ui/base/Interface.js +1 -1
  56. package/src/sap/ui/base/ManagedObject.js +10 -8
  57. package/src/sap/ui/base/ManagedObjectMetadata.js +21 -8
  58. package/src/sap/ui/base/Metadata.js +1 -1
  59. package/src/sap/ui/base/Object.js +1 -1
  60. package/src/sap/ui/base/ObjectPool.js +1 -1
  61. package/src/sap/ui/base/SyncPromise.js +2 -0
  62. package/src/sap/ui/core/.library +1 -89
  63. package/src/sap/ui/core/AppCacheBuster.js +4 -4
  64. package/src/sap/ui/core/BusyIndicator.js +1 -1
  65. package/src/sap/ui/core/Component.js +4 -4
  66. package/src/sap/ui/core/ComponentContainer.js +1 -1
  67. package/src/sap/ui/core/ComponentMetadata.js +1 -1
  68. package/src/sap/ui/core/ComponentSupport.js +1 -1
  69. package/src/sap/ui/core/Configuration.js +1 -1
  70. package/src/sap/ui/core/Control.js +2 -2
  71. package/src/sap/ui/core/Core.js +8 -8
  72. package/src/sap/ui/core/CustomData.js +1 -1
  73. package/src/sap/ui/core/DeclarativeSupport.js +10 -9
  74. package/src/sap/ui/core/Element.js +12 -11
  75. package/src/sap/ui/core/ElementMetadata.js +1 -1
  76. package/src/sap/ui/core/EnabledPropagator.js +4 -2
  77. package/src/sap/ui/core/EventBus.js +1 -1
  78. package/src/sap/ui/core/FocusHandler.js +2 -2
  79. package/src/sap/ui/core/Fragment.js +17 -14
  80. package/src/sap/ui/core/HTML.js +2 -2
  81. package/src/sap/ui/core/History.js +1 -1
  82. package/src/sap/ui/core/Icon.js +6 -6
  83. package/src/sap/ui/core/IconPool.js +1 -3
  84. package/src/sap/ui/core/IndicationColorSupport.js +1 -1
  85. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  86. package/src/sap/ui/core/InvisibleMessage.js +1 -1
  87. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  88. package/src/sap/ui/core/InvisibleText.js +1 -1
  89. package/src/sap/ui/core/Item.js +1 -1
  90. package/src/sap/ui/core/LabelEnablement.js +1 -1
  91. package/src/sap/ui/core/LayoutData.js +1 -1
  92. package/src/sap/ui/core/ListItem.js +1 -1
  93. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  94. package/src/sap/ui/core/Locale.js +28 -4
  95. package/src/sap/ui/core/LocaleData.js +1 -1
  96. package/src/sap/ui/core/Manifest.js +1 -1
  97. package/src/sap/ui/core/Message.js +1 -1
  98. package/src/sap/ui/core/Popup.js +4 -2
  99. package/src/sap/ui/core/RenderManager.js +1 -1
  100. package/src/sap/ui/core/Renderer.js +1 -1
  101. package/src/sap/ui/core/ResizeHandler.js +1 -1
  102. package/src/sap/ui/core/ScrollBar.js +1 -1
  103. package/src/sap/ui/core/SeparatorItem.js +1 -1
  104. package/src/sap/ui/core/ThemeCheck.js +7 -7
  105. package/src/sap/ui/core/Title.js +1 -1
  106. package/src/sap/ui/core/TooltipBase.js +1 -1
  107. package/src/sap/ui/core/UIArea.js +3 -2
  108. package/src/sap/ui/core/UIComponent.js +2 -2
  109. package/src/sap/ui/core/UIComponentMetadata.js +2 -2
  110. package/src/sap/ui/core/ValueStateSupport.js +1 -1
  111. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  112. package/src/sap/ui/core/XMLComposite.js +1 -1
  113. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  114. package/src/sap/ui/core/XMLTemplateProcessor.js +3 -5
  115. package/src/sap/ui/core/cache/LRUPersistentCache.js +2 -1
  116. package/src/sap/ui/core/delegate/ItemNavigation.js +1 -1
  117. package/src/sap/ui/core/delegate/ScrollEnablement.js +1 -1
  118. package/src/sap/ui/core/dnd/DragAndDrop.js +1 -1
  119. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  120. package/src/sap/ui/core/dnd/DragDropInfo.js +1 -1
  121. package/src/sap/ui/core/dnd/DragInfo.js +1 -1
  122. package/src/sap/ui/core/dnd/DropInfo.js +1 -1
  123. package/src/sap/ui/core/format/DateFormat.js +2 -2
  124. package/src/sap/ui/core/format/NumberFormat.js +3 -3
  125. package/src/sap/ui/core/format/TimezoneUtil.js +1 -1
  126. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  127. package/src/sap/ui/core/library.js +3 -3
  128. package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
  129. package/src/sap/ui/core/message/Message.js +1 -1
  130. package/src/sap/ui/core/message/MessageManager.js +1 -1
  131. package/src/sap/ui/core/message/MessageParser.js +2 -2
  132. package/src/sap/ui/core/message/MessageProcessor.js +1 -1
  133. package/src/sap/ui/core/messagebundle_el.properties +2 -2
  134. package/src/sap/ui/core/messagebundle_it.properties +56 -56
  135. package/src/sap/ui/core/mvc/ControllerExtension.js +1 -1
  136. package/src/sap/ui/core/mvc/HTMLView.js +12 -12
  137. package/src/sap/ui/core/mvc/JSONView.js +1 -1
  138. package/src/sap/ui/core/mvc/JSView.js +1 -1
  139. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  140. package/src/sap/ui/core/mvc/View.js +1 -1
  141. package/src/sap/ui/core/mvc/XMLView.js +1 -1
  142. package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
  143. package/src/sap/ui/core/plugin/LessSupport.js +1 -1
  144. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  145. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  146. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  147. package/src/sap/ui/core/routing/History.js +5 -3
  148. package/src/sap/ui/core/routing/Router.js +4 -2
  149. package/src/sap/ui/core/routing/Targets.js +2 -2
  150. package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
  151. package/src/sap/ui/core/search/SearchProvider.js +1 -1
  152. package/src/sap/ui/core/service/Service.js +1 -1
  153. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  154. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  155. package/src/sap/ui/core/support/Plugin.js +1 -1
  156. package/src/sap/ui/core/support/RuleEngineOpaExtension.js +1 -1
  157. package/src/sap/ui/core/support/Support.js +1 -1
  158. package/src/sap/ui/core/support/ToolsAPI.js +4 -1
  159. package/src/sap/ui/core/support/plugins/ControlTree.js +3 -1
  160. package/src/sap/ui/core/support/plugins/Interaction.js +1 -1
  161. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
  162. package/src/sap/ui/core/support/plugins/Performance.js +1 -1
  163. package/src/sap/ui/core/support/plugins/Selector.js +1 -1
  164. package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
  165. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  166. package/src/sap/ui/core/support/plugins/ViewInfo.js +1 -1
  167. package/src/sap/ui/core/theming/Parameters.js +1 -1
  168. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  169. package/src/sap/ui/core/tmpl/DOMElement.js +2 -2
  170. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  171. package/src/sap/ui/core/tmpl/Template.js +4 -4
  172. package/src/sap/ui/core/tmpl/TemplateControl.js +2 -2
  173. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  174. package/src/sap/ui/core/util/Export.js +1 -1
  175. package/src/sap/ui/core/util/ExportCell.js +1 -1
  176. package/src/sap/ui/core/util/ExportColumn.js +1 -1
  177. package/src/sap/ui/core/util/ExportRow.js +1 -1
  178. package/src/sap/ui/core/util/ExportType.js +1 -1
  179. package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
  180. package/src/sap/ui/core/util/File.js +1 -1
  181. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  182. package/src/sap/ui/core/util/MockServer.js +1 -1
  183. package/src/sap/ui/core/util/PasteHelper.js +1 -1
  184. package/src/sap/ui/core/util/ResponsivePaddingsEnablement.js +2 -2
  185. package/src/sap/ui/core/util/XMLPreprocessor.js +1 -1
  186. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
  187. package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
  188. package/src/sap/ui/core/util/serializer/ViewSerializer.js +1 -1
  189. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
  190. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  191. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  192. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  193. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  194. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  195. package/src/sap/ui/core/ws/WebSocket.js +1 -1
  196. package/src/sap/ui/debug/ControlTree.js +1 -1
  197. package/src/sap/ui/debug/DebugEnv.js +1 -1
  198. package/src/sap/ui/debug/PropertyList.js +1 -1
  199. package/src/sap/ui/dom/_ready.js +34 -0
  200. package/src/sap/ui/dom/containsOrEquals.js +2 -2
  201. package/src/sap/ui/dom/getFirstEditableInput.js +2 -2
  202. package/src/sap/ui/dom/jquery/Focusable.js +1 -1
  203. package/src/sap/ui/dom/jquery/control.js +1 -1
  204. package/src/sap/ui/events/jquery/EventExtension.js +1 -1
  205. package/src/sap/ui/events/jquery/EventSimulation.js +1 -1
  206. package/src/sap/ui/model/ClientModel.js +1 -1
  207. package/src/sap/ui/model/CompositeDataState.js +1 -1
  208. package/src/sap/ui/model/CompositeType.js +1 -1
  209. package/src/sap/ui/model/DataState.js +1 -1
  210. package/src/sap/ui/model/MetaModel.js +1 -1
  211. package/src/sap/ui/model/Model.js +1 -1
  212. package/src/sap/ui/model/SelectionModel.js +1 -1
  213. package/src/sap/ui/model/SimpleType.js +1 -1
  214. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  215. package/src/sap/ui/model/TreeBindingAdapter.js +134 -0
  216. package/src/sap/ui/model/Type.js +1 -1
  217. package/src/sap/ui/model/json/JSONModel.js +1 -1
  218. package/src/sap/ui/model/message/MessageModel.js +1 -1
  219. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  220. package/src/sap/ui/model/odata/ODataMessageParser.js +1 -1
  221. package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
  222. package/src/sap/ui/model/odata/ODataMetadata.js +1 -1
  223. package/src/sap/ui/model/odata/ODataModel.js +1 -1
  224. package/src/sap/ui/model/odata/ODataTreeBindingAdapter.js +6 -0
  225. package/src/sap/ui/model/odata/ODataTreeBindingFlat.js +279 -4
  226. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  227. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  228. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  229. package/src/sap/ui/model/odata/type/Date.js +1 -1
  230. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  231. package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
  232. package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
  233. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -1
  234. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  235. package/src/sap/ui/model/odata/type/Double.js +1 -1
  236. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  237. package/src/sap/ui/model/odata/type/Int.js +1 -1
  238. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  239. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  240. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  241. package/src/sap/ui/model/odata/type/ODataType.js +1 -1
  242. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  243. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  244. package/src/sap/ui/model/odata/type/Single.js +1 -1
  245. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  246. package/src/sap/ui/model/odata/type/String.js +1 -1
  247. package/src/sap/ui/model/odata/type/Time.js +1 -1
  248. package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
  249. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  250. package/src/sap/ui/model/odata/v2/Context.js +1 -1
  251. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  252. package/src/sap/ui/model/odata/v2/ODataModel.js +1 -1
  253. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +36 -4
  254. package/src/sap/ui/model/odata/v4/Context.js +7 -10
  255. package/src/sap/ui/model/odata/v4/ODataBinding.js +16 -8
  256. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +24 -1
  257. package/src/sap/ui/model/odata/v4/ODataListBinding.js +29 -2
  258. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +5 -5
  259. package/src/sap/ui/model/odata/v4/ODataModel.js +66 -3
  260. package/src/sap/ui/model/odata/v4/ODataParentBinding.js +30 -1
  261. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +17 -6
  262. package/src/sap/ui/model/odata/v4/lib/_AggregationHelper.js +6 -6
  263. package/src/sap/ui/model/odata/v4/lib/_Cache.js +183 -20
  264. package/src/sap/ui/model/odata/v4/lib/_Helper.js +10 -3
  265. package/src/sap/ui/model/odata/v4/lib/_MinMaxHelper.js +1 -1
  266. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +3 -7
  267. package/src/sap/ui/model/odata/v4/lib/_V2MetadataConverter.js +1 -1
  268. package/src/sap/ui/model/resource/ResourceModel.js +1 -1
  269. package/src/sap/ui/model/type/Boolean.js +1 -1
  270. package/src/sap/ui/model/type/Currency.js +1 -1
  271. package/src/sap/ui/model/type/Date.js +1 -1
  272. package/src/sap/ui/model/type/DateInterval.js +1 -1
  273. package/src/sap/ui/model/type/DateTime.js +1 -1
  274. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  275. package/src/sap/ui/model/type/FileSize.js +1 -1
  276. package/src/sap/ui/model/type/Float.js +1 -1
  277. package/src/sap/ui/model/type/Integer.js +1 -1
  278. package/src/sap/ui/model/type/String.js +1 -1
  279. package/src/sap/ui/model/type/Time.js +1 -1
  280. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  281. package/src/sap/ui/model/type/Unit.js +1 -1
  282. package/src/sap/ui/model/xml/XMLModel.js +1 -1
  283. package/src/sap/ui/qunit/utils/ControlIterator.js +1 -1
  284. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +1 -1
  285. package/src/sap/ui/security/FrameOptions.js +4 -2
  286. package/src/sap/ui/test/OpaBuilder.js +1 -1
  287. package/src/sap/ui/test/OpaPlugin.js +3 -3
  288. package/src/sap/ui/test/_ControlFinder.js +5 -4
  289. package/src/sap/ui/test/actions/Drag.js +2 -2
  290. package/src/sap/ui/test/actions/Drop.js +2 -2
  291. package/src/sap/ui/test/actions/EnterText.js +8 -8
  292. package/src/sap/ui/test/actions/Press.js +5 -5
  293. package/src/sap/ui/test/actions/Scroll.js +1 -1
  294. package/src/sap/ui/test/generic/TestBase.js +1 -1
  295. package/src/sap/ui/util/Mobile.js +59 -33
  296. package/src/sap/ui/util/Storage.js +2 -2
  297. package/src/sap/ui/util/openWindow.js +1 -1
  298. package/src/ui5loader.js +3 -3
  299. package/ui5.yaml +71 -0
@@ -58,7 +58,7 @@ sap.ui.define([
58
58
  * @mixes sap.ui.model.odata.v4.ODataParentBinding
59
59
  * @public
60
60
  * @since 1.37.0
61
- * @version 1.102.1
61
+ * @version 1.103.1
62
62
  * @borrows sap.ui.model.odata.v4.ODataBinding#getGroupId as #getGroupId
63
63
  * @borrows sap.ui.model.odata.v4.ODataBinding#getRootBinding as #getRootBinding
64
64
  * @borrows sap.ui.model.odata.v4.ODataBinding#getUpdateGroupId as #getUpdateGroupId
@@ -1380,6 +1380,8 @@ sap.ui.define([
1380
1380
  return oPromise.then(function (oResult) {
1381
1381
  var oError;
1382
1382
 
1383
+ // Without the bAsync flag we would need the following test twice: once here for the
1384
+ // createContexts and once in the caller to be safe after the additional hop
1383
1385
  if (!that.aContexts) {
1384
1386
  oError = new Error("Binding already destroyed");
1385
1387
  oError.canceled = true;
@@ -1689,6 +1691,31 @@ sap.ui.define([
1689
1691
  });
1690
1692
  };
1691
1693
 
1694
+ /**
1695
+ * @override
1696
+ * @see sap.ui.model.odata.v4.ODataParentBinding#findContextForCanonicalPath
1697
+ */
1698
+ ODataListBinding.prototype.findContextForCanonicalPath = function (sCanonicalPath) {
1699
+ var aKeptAliveContexts = Object.values(this.mPreviousContextsByPath)
1700
+ .filter(function (oCandidate) {
1701
+ return oCandidate.isKeepAlive();
1702
+ });
1703
+
1704
+ function check(aContexts) {
1705
+ return aContexts.find(function (oCandidate) {
1706
+ var oPromise;
1707
+
1708
+ if (oCandidate) {
1709
+ oPromise = oCandidate.fetchCanonicalPath();
1710
+ oPromise.caught();
1711
+ return oPromise.getResult() === sCanonicalPath;
1712
+ }
1713
+ });
1714
+ }
1715
+
1716
+ return check(aKeptAliveContexts) || check(this.aContexts);
1717
+ };
1718
+
1692
1719
  /**
1693
1720
  * Filters the list with the given filters. Since 1.97.0, if filters are unchanged, no request
1694
1721
  * is sent, regardless of pending changes.
@@ -1842,7 +1869,7 @@ sap.ui.define([
1842
1869
  * binding, its contexts are moved here, it is destroyed and its cache is returned.
1843
1870
  *
1844
1871
  * @param {string} sResourcePath
1845
- * The resoure path for the cache
1872
+ * The resource path for the cache
1846
1873
  * @param {object} mQueryOptions
1847
1874
  * The query options for the cache
1848
1875
  * @returns {sap.ui.model.odata.v4.lib._CollectionCache|undefined}
@@ -157,7 +157,7 @@ sap.ui.define([
157
157
  * @hideconstructor
158
158
  * @public
159
159
  * @since 1.37.0
160
- * @version 1.102.1
160
+ * @version 1.103.1
161
161
  */
162
162
  ODataMetaModel = MetaModel.extend("sap.ui.model.odata.v4.ODataMetaModel", {
163
163
  constructor : constructor
@@ -2178,7 +2178,7 @@ sap.ui.define([
2178
2178
  * or a constraint if not needed.
2179
2179
  *
2180
2180
  * @param {string} sKey The constraint's name
2181
- * @param {any} vValue The contraint's value
2181
+ * @param {any} vValue The constraint's value
2182
2182
  */
2183
2183
  function setConstraint(sKey, vValue) {
2184
2184
  if (vValue !== undefined) {
@@ -3245,10 +3245,10 @@ sap.ui.define([
3245
3245
  })).then(function (aResults) {
3246
3246
  // insert the returned mappings into oValueListInfo in the order of aMappingUrls
3247
3247
  aMappingUrls.forEach(function (sMappingUrl, i) {
3248
- var mvalueListMappingByQualifier = aResults[i].valueListMappingByQualifier;
3248
+ var mValueListMappingByQualifier = aResults[i].valueListMappingByQualifier;
3249
3249
 
3250
- Object.keys(mvalueListMappingByQualifier).forEach(function (sQualifier) {
3251
- addMapping(mvalueListMappingByQualifier[sQualifier], sQualifier,
3250
+ Object.keys(mValueListMappingByQualifier).forEach(function (sQualifier) {
3251
+ addMapping(mValueListMappingByQualifier[sQualifier], sQualifier,
3252
3252
  sMappingUrl, aResults[i].$model);
3253
3253
  });
3254
3254
  });
@@ -214,7 +214,7 @@ sap.ui.define([
214
214
  * @extends sap.ui.model.Model
215
215
  * @public
216
216
  * @since 1.37.0
217
- * @version 1.102.1
217
+ * @version 1.103.1
218
218
  */
219
219
  ODataModel = Model.extend("sap.ui.model.odata.v4.ODataModel",
220
220
  /** @lends sap.ui.model.odata.v4.ODataModel.prototype */{
@@ -888,7 +888,7 @@ sap.ui.define([
888
888
  sExpandPath,
889
889
  vValue = mOptions[sOptionName];
890
890
 
891
- if (!bSystemQueryOptionsAllowed || aAllowed.indexOf(sOptionName) < 0) {
891
+ if (!bSystemQueryOptionsAllowed || !aAllowed.includes(sOptionName)) {
892
892
  throw new Error("System query option " + sOptionName + " is not supported");
893
893
  }
894
894
  if ((sOptionName === "$expand" || sOptionName === "$select")
@@ -1255,6 +1255,69 @@ sap.ui.define([
1255
1255
  });
1256
1256
  };
1257
1257
 
1258
+ /**
1259
+ * Deletes the entity with the given canonical path on the server and in all bindings. Pending
1260
+ * changes in contexts for this entity or in dependents thereof are canceled.
1261
+ *
1262
+ * Deleting in the bindings is only possible if the given path is a canonical path, and all
1263
+ * paths follow these rules in addition to the OData 4.0 specification:
1264
+ * <ul>
1265
+ * <li> Key properties are ordered just as in the metadata,
1266
+ * <li> for single key properties, the name of the key is omitted,
1267
+ * <li> for collection-valued navigation properties, all keys are present,
1268
+ * <li> the key-value pairs are encoded via encodeURIComponent.
1269
+ * </ul>
1270
+ *
1271
+ * @param {string} sCanonicalPath
1272
+ * The canonical path of the entity to delete, starting with a '/'
1273
+ * @param {string} [sGroupId]
1274
+ * The group ID that is used for the DELETE request; if not specified, the model's
1275
+ * {@link #getUpdateGroupId update group ID} is used; the resulting group ID must not have
1276
+ * {@link sap.ui.model.odata.v4.SubmitMode.API}
1277
+ * @param {boolean} [bRejectIfNotFound]
1278
+ * If <code>true</code>, deletion fails if the entity does not exist (HTTP status code 404 or
1279
+ * 412 due to the <code>If-Match: *</code> header); otherwise we assume that it has already
1280
+ * been deleted by someone else and report success
1281
+ * @returns {Promise}
1282
+ * A promise resolving when the delete succeeded, and rejecting with an instance of Error
1283
+ * otherwise. In the latter case the HTTP status code of the response is given in the error's
1284
+ * property <code>status</code>.
1285
+ * @throws {Error} If
1286
+ * <ul>
1287
+ * <li> the path does not start with a '/',
1288
+ * <li> the given group ID is invalid,
1289
+ * <li> the resulting group ID has {@link sap.ui.model.odata.v4.SubmitMode.API}.
1290
+ * </ul>
1291
+ *
1292
+ * @public
1293
+ * @since 1.103.0
1294
+ */
1295
+ ODataModel.prototype.delete = function (sCanonicalPath, sGroupId, bRejectIfNotFound) {
1296
+ var that = this;
1297
+
1298
+ if (sCanonicalPath[0] !== "/") {
1299
+ throw new Error("Invalid path: " + sCanonicalPath);
1300
+ }
1301
+ this.checkGroupId(sGroupId);
1302
+ sGroupId = sGroupId || this.getUpdateGroupId();
1303
+ if (this.isApiGroup(sGroupId)) {
1304
+ throw new Error("Illegal update group ID: " + sGroupId);
1305
+ }
1306
+
1307
+ return this.oRequestor.request("DELETE", sCanonicalPath.slice(1),
1308
+ this.lockGroup(sGroupId, this, true, true),
1309
+ {"If-Match" : "*"}
1310
+ ).catch(function (oError) {
1311
+ if (oError.status !== 404 && oError.status !== 412 || bRejectIfNotFound) {
1312
+ throw oError;
1313
+ } // else: map 404/412 to 200
1314
+ }).then(function () {
1315
+ that.aAllBindings.forEach(function (oBinding) {
1316
+ oBinding.onDelete(sCanonicalPath);
1317
+ });
1318
+ });
1319
+ };
1320
+
1258
1321
  /**
1259
1322
  * Destroys this model, its requestor and its meta model.
1260
1323
  *
@@ -2033,7 +2096,7 @@ sap.ui.define([
2033
2096
 
2034
2097
  // could be async, but normally in this state we should already have
2035
2098
  // loaded the needed metadata
2036
- oType = that.oRequestor.fetchTypeForPath("/" + sMetaPath).getResult();
2099
+ oType = that.oMetaModel.getObject("/" + sMetaPath + "/");
2037
2100
 
2038
2101
  if (!(oType && oType.$Key)) {
2039
2102
  bFailed = true;
@@ -102,6 +102,19 @@ sap.ui.define([
102
102
  // nothing to do here
103
103
  };
104
104
 
105
+ /**
106
+ * Finds the context that matches the given canonical path.
107
+ *
108
+ * @param {string} sCanonicalPath
109
+ * The canonical path of an entity (as a context path with the leading "/")
110
+ * @returns {sap.ui.model.odata.v4.Context}
111
+ * A matching context or <code>undefined</code> if there is none
112
+ *
113
+ * @function
114
+ * @name sap.ui.model.odata.v4.ODataParentBinding#findContextForCanonicalPath
115
+ * @private
116
+ */
117
+
105
118
  /**
106
119
  * Fire event 'patchCompleted' to attached listeners, if the last PATCH request is completed.
107
120
  *
@@ -246,7 +259,7 @@ sap.ui.define([
246
259
  * @returns {boolean} Whether the query options can be fulfilled by this binding
247
260
  */
248
261
  function mergeSelectPath(sSelectPath) {
249
- if (mAggregatedQueryOptions.$select.indexOf(sSelectPath) < 0) {
262
+ if (!mAggregatedQueryOptions.$select.includes(sSelectPath)) {
250
263
  mAggregatedQueryOptions.$select.push(sSelectPath);
251
264
  }
252
265
  return true;
@@ -1067,6 +1080,22 @@ sap.ui.define([
1067
1080
  return false;
1068
1081
  };
1069
1082
 
1083
+ /**
1084
+ * @override
1085
+ * @see sap.ui.model.odata.v4.ODataBinding#onDelete
1086
+ */
1087
+ ODataParentBinding.prototype.onDelete = function (sCanonicalPath) {
1088
+ var oContext = this.findContextForCanonicalPath(sCanonicalPath);
1089
+
1090
+ if (oContext) {
1091
+ this.resetChangesForPath(this.getRelativePath(oContext.getPath()), []);
1092
+ this.oModel.getDependentBindings(oContext).forEach(function (oBinding) {
1093
+ oBinding.resetChanges();
1094
+ });
1095
+ this._delete(null, sCanonicalPath.slice(1), oContext);
1096
+ }
1097
+ };
1098
+
1070
1099
  /**
1071
1100
  * Recursively refreshes all dependent list bindings that have no own cache.
1072
1101
  *
@@ -42,7 +42,7 @@ sap.ui.define([
42
42
  * @mixes sap.ui.model.odata.v4.ODataBinding
43
43
  * @public
44
44
  * @since 1.37.0
45
- * @version 1.102.1
45
+ * @version 1.103.1
46
46
  * @borrows sap.ui.model.odata.v4.ODataBinding#getGroupId as #getGroupId
47
47
  * @borrows sap.ui.model.odata.v4.ODataBinding#getRootBinding as #getRootBinding
48
48
  * @borrows sap.ui.model.odata.v4.ODataBinding#getUpdateGroupId as #getUpdateGroupId
@@ -369,10 +369,9 @@ sap.ui.define([
369
369
  var that = this;
370
370
 
371
371
  this.withCache(function (_oCache, sPath, oBinding) {
372
- oBinding.doDeregisterChangeListener(sPath, that);
373
- }).catch(function (oError) {
374
- that.oModel.reportError("Error in deregisterChange", sClassName, oError);
375
- }, /*sPath*/"", /*bSync*/false, /*bWithOrWithoutCache*/true);
372
+ oBinding.doDeregisterChangeListener(sPath, that);
373
+ }, /*sPath*/"", /*bSync*/false, /*bWithOrWithoutCache*/true)
374
+ .catch(this.oModel.getReporter());
376
375
  };
377
376
 
378
377
  /**
@@ -502,6 +501,14 @@ sap.ui.define([
502
501
  .catch(this.oModel.getReporter());
503
502
  };
504
503
 
504
+ /**
505
+ * @override
506
+ * @see sap.ui.model.odata.v4.ODataBinding#onDelete
507
+ */
508
+ ODataPropertyBinding.prototype.onDelete = function () {
509
+ // nothing to do
510
+ };
511
+
505
512
  /**
506
513
  * @override
507
514
  * @see sap.ui.model.odata.v4.ODataBinding#refreshInternal
@@ -515,7 +522,11 @@ sap.ui.define([
515
522
  return SyncPromise.resolve();
516
523
  }
517
524
  return this.oCachePromise.then(function () {
518
- that.fetchCache(that.oContext, false, /*bKeepQueryOptions*/true, bKeepCacheOnError);
525
+ if (that.oCache && that.oCache.reset) {
526
+ that.oCache.reset();
527
+ } else {
528
+ that.fetchCache(that.oContext, false, /*bKeepQueryOptions*/true, bKeepCacheOnError);
529
+ }
519
530
 
520
531
  if (bCheckUpdate) {
521
532
  return that.checkUpdateInternal(undefined, ChangeReason.Refresh, sGroupId);
@@ -83,8 +83,8 @@ sap.ui.define([
83
83
  }
84
84
  aAggregate.push(sAggregate);
85
85
 
86
- if (sUnit && aAggregate.indexOf(sUnit) < 0 && aAliases.indexOf(sUnit, i + 1) < 0
87
- && aGroupBy.indexOf(sUnit) < 0) {
86
+ if (sUnit && !aAggregate.includes(sUnit) && !aAliases.includes(sUnit, i + 1)
87
+ && !aGroupBy.includes(sUnit)) {
88
88
  aAggregate.push(sUnit);
89
89
  }
90
90
  }
@@ -233,7 +233,7 @@ sap.ui.define([
233
233
  });
234
234
  aGroupBy = bIsLeafLevel
235
235
  ? Object.keys(oAggregation.group).sort().filter(function (sGroup) {
236
- return oAggregation.groupLevels.indexOf(sGroup) < 0;
236
+ return !oAggregation.groupLevels.includes(sGroup);
237
237
  })
238
238
  : [oAggregation.groupLevels[iLevel - 1]];
239
239
  if (!iLevel) {
@@ -559,14 +559,14 @@ sap.ui.define([
559
559
  */
560
560
  function isUsedAtLeaf(sName) {
561
561
  if (sName in oAggregation.group
562
- && (!iLevel || oAggregation.groupLevels.indexOf(sName) < 0)) {
562
+ && (!iLevel || !oAggregation.groupLevels.includes(sName))) {
563
563
  return true; // "quick path"
564
564
  }
565
565
 
566
566
  return Object.keys(oAggregation.aggregate).some(function (sAlias) {
567
567
  return sName === oAggregation.aggregate[sAlias].unit;
568
568
  }) || Object.keys(oAggregation.group).some(function (sGroup) {
569
- return (!iLevel || oAggregation.groupLevels.indexOf(sGroup) < 0)
569
+ return (!iLevel || !oAggregation.groupLevels.includes(sGroup))
570
570
  && isUsedFor(sName, sGroup);
571
571
  });
572
572
  }
@@ -581,7 +581,7 @@ sap.ui.define([
581
581
  function isUsedFor(sName, sGroup) {
582
582
  return sName === sGroup
583
583
  || oAggregation.group[sGroup].additionally
584
- && oAggregation.group[sGroup].additionally.indexOf(sName) >= 0;
584
+ && oAggregation.group[sGroup].additionally.includes(sName);
585
585
  }
586
586
 
587
587
  if (sOrderby) {
@@ -206,7 +206,7 @@ sap.ui.define([
206
206
  }),
207
207
  iIndex === undefined // single element or kept-alive not in list
208
208
  && !bDoNotRequestCount
209
- && that.requestCount(oGroupLock),
209
+ && that.requestCount(oGroupLock || that.oRequestor.lockGroup("$auto", that)),
210
210
  oGroupLock && oGroupLock.unlock() // unlock when all requests have been queued
211
211
  ]).then(function () {
212
212
  if (Array.isArray(vCacheData)) {
@@ -398,8 +398,7 @@ sap.ui.define([
398
398
  aSelect = _Helper.getQueryOptionsForPath(that.mQueryOptions, sPath).$select;
399
399
  _Helper.updateSelected(that.mChangeListeners,
400
400
  _Helper.buildPath(sPath, sPredicate || sTransientPredicate), oEntityData,
401
- oCreatedEntity,
402
- aSelect && aSelect.concat("@odata.etag")); // do not change $select
401
+ oCreatedEntity, aSelect);
403
402
 
404
403
  that.removePendingRequest();
405
404
  fnResolve(true);
@@ -508,6 +507,7 @@ sap.ui.define([
508
507
  var oDataPromise = SyncPromise.resolve(oData),
509
508
  oEntity,
510
509
  iEntityPathLength,
510
+ bInAnnotation = false,
511
511
  aSegments,
512
512
  bTransient = false,
513
513
  that = this;
@@ -522,21 +522,42 @@ sap.ui.define([
522
522
  * Determines the implicit value if the value is missing in the cache. Reports an invalid
523
523
  * segment if there is no @Core.Permissions: 'None' annotation and no implicit value.
524
524
  *
525
- * @param {object} oValue The object that is expected to have the value
526
- * @param {string} sSegment The path segment that is missing
527
- * @param {number} iPathLength The length of the path of the missing value
528
- * @returns {any} The value if it could be determined or undefined otherwise
525
+ * @param {object} oValue - The object that is expected to have the value
526
+ * @param {string} sSegment - The path segment that is missing
527
+ * @param {number} iPathLength - The length of the path of the missing value
528
+ * @returns {sap.ui.base.SyncPromise|undefined}
529
+ * Returns a SyncPromise which resolves with the value or returns undefined in some
530
+ * special cases.
529
531
  */
530
532
  function missingValue(oValue, sSegment, iPathLength) {
531
533
  var sPropertyPath = aSegments.slice(0, iPathLength).join("/"),
534
+ sPropertyName,
532
535
  sReadLink,
533
536
  sServiceUrl;
534
537
 
535
538
  if (Array.isArray(oValue)) {
536
539
  return invalidSegment(sSegment, sSegment === "0"); // missing key predicate or index
537
540
  }
541
+
542
+ if (bInAnnotation) {
543
+ return invalidSegment(sSegment, true);
544
+ }
545
+
546
+ if (sSegment.includes("@")) { // missing property annotation
547
+ sPropertyName = sSegment.split("@")[0];
548
+ if (bTransient
549
+ || sPropertyName in oValue
550
+ || oValue[sPropertyName + "@$ui5.noData"]
551
+ || (that.mQueryOptions
552
+ && that.mQueryOptions.$select.includes(sPropertyPath.split("@")[0]))) {
553
+ // no use to send late request
554
+ return invalidSegment(sSegment, true);
555
+ }
556
+ }
557
+
538
558
  return that.oRequestor.getModelInterface()
539
- .fetchMetadata(that.sMetaPath + "/" + _Helper.getMetaPath(sPropertyPath))
559
+ .fetchMetadata(that.sMetaPath + "/"
560
+ + _Helper.getMetaPath(sPropertyPath.split("@")[0]))
540
561
  .then(function (oProperty) {
541
562
  var vPermissions;
542
563
 
@@ -566,7 +587,7 @@ sap.ui.define([
566
587
  return oEntity
567
588
  && that.fetchLateProperty(oGroupLock, oEntity,
568
589
  aSegments.slice(0, iEntityPathLength).join("/"),
569
- aSegments.slice(iEntityPathLength).join("/"),
590
+ aSegments.slice(iEntityPathLength).join("/").split("@")[0],
570
591
  aSegments.slice(iEntityPathLength, iPathLength).join("/"))
571
592
  || invalidSegment(sSegment);
572
593
  }
@@ -634,9 +655,14 @@ sap.ui.define([
634
655
  vValue = vValue[vIndex];
635
656
  }
636
657
  // missing advertisement or annotation is not an error
637
- return vValue === undefined && sSegment[0] !== "#" && !sSegment.includes("@")
658
+ vValue = vValue === undefined && sSegment[0] !== "#" && sSegment[0] !== "@"
638
659
  ? missingValue(oParentValue, sSegment, i + 1)
639
660
  : vValue;
661
+ if (sSegment.includes("@")) {
662
+ bInAnnotation = true;
663
+ }
664
+
665
+ return vValue;
640
666
  });
641
667
  }, oDataPromise);
642
668
  };
@@ -762,11 +788,12 @@ sap.ui.define([
762
788
  // even when two late properties lead to the same request, each of them must be copied to
763
789
  // the cache.
764
790
  return oPromise.then(function (oData) {
765
- var sPredicate = _Helper.getPrivateAnnotation(oData, "predicate");
791
+ var sNewPredicate = _Helper.getPrivateAnnotation(oData, "predicate"),
792
+ sOldPredicate = _Helper.getPrivateAnnotation(oResource, "predicate");
766
793
 
767
- if (sPredicate && _Helper.getPrivateAnnotation(oResource, "predicate") !== sPredicate) {
794
+ if (sOldPredicate && sNewPredicate && sOldPredicate !== sNewPredicate) {
768
795
  throw new Error("GET " + sRequestPath + ": Key predicate changed from "
769
- + _Helper.getPrivateAnnotation(oResource, "predicate") + " to " + sPredicate);
796
+ + sOldPredicate + " to " + sNewPredicate);
770
797
  }
771
798
  // we expect the server to always or never send an ETag for this entity
772
799
  if (oResource["@odata.etag"] && oData["@odata.etag"] !== oResource["@odata.etag"]) {
@@ -1340,7 +1367,7 @@ sap.ui.define([
1340
1367
  delete aElements.$byPredicate[sTransientPredicate];
1341
1368
  }
1342
1369
  if (!sPath && iIndex !== undefined) {
1343
- // Note: sPath is empty only in a CollectionCache, so we may use iLmit and
1370
+ // Note: sPath is empty only in a CollectionCache, so we may use iLimit and
1344
1371
  // adjustReadRequests
1345
1372
  if (!sTransientPredicate) {
1346
1373
  this.iLimit -= 1; // this doesn't change Infinity
@@ -2022,8 +2049,8 @@ sap.ui.define([
2022
2049
  || sProperty.endsWith("@mediaReadLink")) {
2023
2050
  oInstance[sProperty] = _Helper.makeAbsolute(vPropertyValue, sContextUrl);
2024
2051
  }
2025
- if (sProperty.includes("@")) { // ignore other annotations
2026
- return;
2052
+ if (sProperty === sMessageProperty || sProperty.includes("@")) {
2053
+ return; // ignore message property and other annotations
2027
2054
  }
2028
2055
  if (Array.isArray(vPropertyValue)) {
2029
2056
  vPropertyValue.$created = 0; // number of (client-side) created elements
@@ -3163,20 +3190,27 @@ sap.ui.define([
3163
3190
  * requests for late properties. If <code>false<code>, {@link #post} throws an error.
3164
3191
  * @param {string} [sMetaPath]
3165
3192
  * Optional meta path in case it cannot be derived from the given resource path
3166
- *
3193
+ * @param {boolean} [bEmpty]
3194
+ * Whether the cache is initialized with an empty response so that all properties are fetched
3195
+ * as late properties
3167
3196
  * @alias sap.ui.model.odata.v4.lib._SingleCache
3168
3197
  * @constructor
3169
3198
  * @private
3170
3199
  */
3171
3200
  function _SingleCache(oRequestor, sResourcePath, mQueryOptions, bSortExpandSelect,
3172
- bSharedRequest, fnGetOriginalResourcePath, bPost, sMetaPath) {
3201
+ bSharedRequest, fnGetOriginalResourcePath, bPost, sMetaPath, bEmpty) {
3173
3202
  _Cache.call(this, oRequestor, sResourcePath, mQueryOptions, bSortExpandSelect,
3174
3203
  fnGetOriginalResourcePath, bSharedRequest);
3175
3204
 
3176
3205
  this.sMetaPath = sMetaPath || this.sMetaPath; // overrides Cache c'tor
3177
3206
  this.bPost = bPost;
3178
3207
  this.bPosting = false;
3179
- this.oPromise = null; // a SyncPromise for the current value
3208
+ if (bEmpty) {
3209
+ // simulates an empty response and ensure that all properties become late properties
3210
+ this.oPromise = SyncPromise.resolve({});
3211
+ } else {
3212
+ this.oPromise = null; // a SyncPromise for the current value
3213
+ }
3180
3214
  }
3181
3215
 
3182
3216
  // make SingleCache a Cache
@@ -3452,6 +3486,132 @@ sap.ui.define([
3452
3486
  return oResult;
3453
3487
  };
3454
3488
 
3489
+ /**
3490
+ * Resets the property for the given path. This means that the next #fetchValue will request the
3491
+ * property again via #fetchLateProperty. Deletes also the entity's ETag within the cache in
3492
+ * order to allow that it may change.
3493
+ *
3494
+ * @param {string} sPath - The path to the property within the cache
3495
+ */
3496
+ _SingleCache.prototype.resetProperty = function (sPath) {
3497
+ var oData = this.oPromise.getResult();
3498
+
3499
+ if (oData) {
3500
+ sPath.split("/").some(function (sProperty) {
3501
+ // Note: all ETags that are reached by the given sPath are deleted in order to
3502
+ // prevent that #fetchLateProperty throws "Key predicate changed from ..."
3503
+ // Ideally only the ETag for the entity the property belongs to should be deleted.
3504
+ // But because PATCH within SingletonPropertyCache is anyhow not supported we can
3505
+ // delete all ETags so far
3506
+ delete oData["@odata.etag"];
3507
+ if (typeof oData[sProperty] === "object") {
3508
+ oData = oData[sProperty];
3509
+ return false;
3510
+ }
3511
+ delete oData[sProperty];
3512
+ return true;
3513
+ });
3514
+ }
3515
+ };
3516
+
3517
+ //*********************************************************************************************
3518
+ // SingletonPropertyCache
3519
+ //*********************************************************************************************
3520
+ /**
3521
+ * Creates a cache for a property that belongs to an OData singleton by creating a _SingleCache
3522
+ * for the singleton and remembering the property path within that _SingleCache. All
3523
+ * _SingletonPropertyCaches that belong to the same singleton share the same _SingleCache if
3524
+ * they have the same query options.
3525
+ *
3526
+ * @param {sap.ui.model.odata.v4.lib._Requestor} oRequestor
3527
+ * The requestor
3528
+ * @param {string} sResourcePath
3529
+ * A resource path relative to the service URL
3530
+ * @param {object} [mQueryOptions]
3531
+ * A map of key-value pairs representing the query string
3532
+ * @private
3533
+ */
3534
+ function _SingletonPropertyCache(oRequestor, sResourcePath, mQueryOptions) {
3535
+ var aSegments = sResourcePath.split("/"),
3536
+ sSingleton = aSegments[0],
3537
+ sSingletonKey = sSingleton + JSON.stringify(mQueryOptions),
3538
+ mSingletonCacheByPath = oRequestor.$mSingletonCacheByPath;
3539
+
3540
+ _PropertyCache.call(this, oRequestor, sResourcePath,
3541
+ {/*mQueryOptions will be passed to the _SingleCache*/});
3542
+
3543
+ if (!mSingletonCacheByPath) {
3544
+ mSingletonCacheByPath = oRequestor.$mSingletonCacheByPath = {};
3545
+ }
3546
+ this.oSingleton = mSingletonCacheByPath[sSingletonKey];
3547
+ if (!this.oSingleton) {
3548
+ this.oSingleton = mSingletonCacheByPath[sSingletonKey]
3549
+ = new _SingleCache(oRequestor, sSingleton, mQueryOptions,
3550
+ /*bSortExpandSelect*/ undefined, /*bSharedRequest*/ undefined,
3551
+ /*fnGetOriginalResourcePath*/ undefined, /*bPost*/ undefined,
3552
+ /*sMetaPath*/ undefined, /*bEmpty*/ true);
3553
+ }
3554
+ this.sRelativePath = sResourcePath.split(sSingleton + "/")[1];
3555
+ }
3556
+
3557
+ // make _SingletonPropertyCache a _PropertyCache
3558
+ _SingletonPropertyCache.prototype = Object.create(_PropertyCache.prototype);
3559
+
3560
+ /**
3561
+ * Delegates to #fetchValue of its shared OData Singleton _SingleCache. Within the 1st call its
3562
+ * own relative property path is added to the mLateQueryOptions of its _SingleCache.
3563
+ *
3564
+ * @param {sap.ui.model.odata.v4.lib._GroupLock} oGroupLock
3565
+ * A lock for the group to associate the request with
3566
+ * see {sap.ui.model.odata.v4.lib._Requestor#request} for details
3567
+ * @param {string} [_sPath]
3568
+ * ignored for property caches, should be empty
3569
+ * @param {function} [fnDataRequested]
3570
+ * The function is called just before the back-end request is sent.
3571
+ * @param {object} [oListener]
3572
+ * A change listener that is added for the given path. Its method <code>onChange</code> is
3573
+ * called with the new value if the property at that path is modified later
3574
+ * @param {boolean} [bCreateOnDemand]
3575
+ * Unsupported
3576
+ * @returns {sap.ui.base.SyncPromise}
3577
+ * A promise to be resolved with the value. It is rejected if the request for the data failed.
3578
+ * @throws {Error}
3579
+ * If <code>bCreateOnDemand</code> is set or if group ID is '$cached' and the value is not
3580
+ * cached (the error has a property <code>$cached = true</code> then)
3581
+ *
3582
+ * @public
3583
+ */
3584
+ _SingletonPropertyCache.prototype.fetchValue = function (oGroupLock, _sPath, fnDataRequested,
3585
+ oListener, bCreateOnDemand) {
3586
+ var sPropertyPath = this.oSingleton.sResourcePath + "/" + this.sRelativePath,
3587
+ mLateQueryOptions,
3588
+ oMetadataPromise = this.oMetadataPromise || this.oRequestor.getModelInterface()
3589
+ .fetchMetadata("/" + _Helper.getMetaPath(sPropertyPath)),
3590
+ that = this;
3591
+
3592
+ return oMetadataPromise.then(function () {
3593
+ if (!that.oMetadataPromise) {
3594
+ mLateQueryOptions = that.oSingleton.getLateQueryOptions() || {};
3595
+ _Helper.aggregateExpandSelect(mLateQueryOptions,
3596
+ _Helper.wrapChildQueryOptions("/" + that.oSingleton.sResourcePath,
3597
+ that.sRelativePath, {}, that.oRequestor.getModelInterface().fetchMetadata));
3598
+ that.oSingleton.setLateQueryOptions(mLateQueryOptions);
3599
+ }
3600
+ that.oMetadataPromise = oMetadataPromise;
3601
+ return that.oSingleton.fetchValue(oGroupLock, that.sRelativePath, fnDataRequested,
3602
+ oListener, bCreateOnDemand);
3603
+ });
3604
+ };
3605
+
3606
+ /**
3607
+ * Resets the property for its own relative path within the singleton's single cache. This means
3608
+ * that the next #fetchValue will request the property again via #fetchLateProperty. Deletes
3609
+ * also the entity's ETag within the cache in order to allow that it may change.
3610
+ */
3611
+ _SingletonPropertyCache.prototype.reset = function () {
3612
+ this.oSingleton.resetProperty(this.sRelativePath);
3613
+ };
3614
+
3455
3615
  //*********************************************************************************************
3456
3616
  // "static" functions
3457
3617
  //*********************************************************************************************
@@ -3550,7 +3710,10 @@ sap.ui.define([
3550
3710
  * @public
3551
3711
  */
3552
3712
  _Cache.createProperty = function (oRequestor, sResourcePath, mQueryOptions) {
3553
- return new _PropertyCache(oRequestor, sResourcePath, mQueryOptions);
3713
+ if (sResourcePath.includes("(") || sResourcePath.endsWith("/$count")) {
3714
+ return new _PropertyCache(oRequestor, sResourcePath, mQueryOptions);
3715
+ }
3716
+ return new _SingletonPropertyCache(oRequestor, sResourcePath, mQueryOptions);
3554
3717
  };
3555
3718
 
3556
3719
  /**
@@ -48,7 +48,7 @@ sap.ui.define([
48
48
  if (oItem) {
49
49
  if (!mMap[sPath]) {
50
50
  mMap[sPath] = [oItem];
51
- } else if (mMap[sPath].indexOf(oItem) < 0) {
51
+ } else if (!mMap[sPath].includes(oItem)) {
52
52
  mMap[sPath].push(oItem);
53
53
  }
54
54
  }
@@ -70,7 +70,7 @@ sap.ui.define([
70
70
  aChildren.forEach(function (sPath) {
71
71
  var aSegments;
72
72
 
73
- if (aAncestors.indexOf(sPath) >= 0) {
73
+ if (aAncestors.includes(sPath)) {
74
74
  mChildren[sPath] = true;
75
75
  return;
76
76
  }
@@ -97,7 +97,7 @@ sap.ui.define([
97
97
  addToSelect : function (mQueryOptions, aSelectPaths) {
98
98
  mQueryOptions.$select = mQueryOptions.$select || [];
99
99
  aSelectPaths.forEach(function (sPath) {
100
- if (mQueryOptions.$select.indexOf(sPath) < 0) {
100
+ if (!mQueryOptions.$select.includes(sPath)) {
101
101
  mQueryOptions.$select.push(sPath);
102
102
  }
103
103
  });
@@ -2175,6 +2175,13 @@ sap.ui.define([
2175
2175
  }
2176
2176
  });
2177
2177
 
2178
+ // Create annotations for a property which was selected but no data was received
2179
+ Object.keys(vSelect).forEach(function (sProperty) {
2180
+ if (!(sProperty in oTarget)) {
2181
+ oTarget[sProperty + "@$ui5.noData"] = true;
2182
+ }
2183
+ });
2184
+
2178
2185
  return oTarget;
2179
2186
  }
2180
2187