@openui5/sap.ui.core 1.97.1 → 1.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (441) hide show
  1. package/.eslintrc.json +92 -2
  2. package/.reuse/dep5 +25 -30
  3. package/THIRDPARTY.txt +15 -22
  4. package/package.json +1 -1
  5. package/src/jquery.sap.global.js +6 -3
  6. package/src/jquery.sap.mobile.js +29 -19
  7. package/src/jquery.sap.properties.js +1 -1
  8. package/src/jquery.sap.resources.js +1 -1
  9. package/src/jquery.sap.script.js +1 -1
  10. package/src/jquery.sap.storage.js +3 -3
  11. package/src/sap/base/Log.js +1 -1
  12. package/src/sap/base/strings/whitespaceReplacer.js +1 -1
  13. package/src/sap/base/util/LoaderExtensions.js +1 -10
  14. package/src/sap/base/util/UriParameters.js +2 -2
  15. package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
  16. package/src/sap/base/util/restricted/_castArray.js +1 -1
  17. package/src/sap/base/util/restricted/_compact.js +1 -1
  18. package/src/sap/base/util/restricted/_curry.js +1 -1
  19. package/src/sap/base/util/restricted/_debounce.js +1 -1
  20. package/src/sap/base/util/restricted/_difference.js +1 -1
  21. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  22. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  23. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  24. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  25. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  26. package/src/sap/base/util/restricted/_flatten.js +1 -1
  27. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  28. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  29. package/src/sap/base/util/restricted/_intersection.js +1 -1
  30. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  31. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  32. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  33. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  34. package/src/sap/base/util/restricted/_isNil.js +1 -1
  35. package/src/sap/base/util/restricted/_max.js +1 -1
  36. package/src/sap/base/util/restricted/_merge.js +1 -1
  37. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  38. package/src/sap/base/util/restricted/_min.js +1 -1
  39. package/src/sap/base/util/restricted/_omit.js +1 -1
  40. package/src/sap/base/util/restricted/_pick.js +1 -1
  41. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  42. package/src/sap/base/util/restricted/_throttle.js +1 -1
  43. package/src/sap/base/util/restricted/_toArray.js +1 -1
  44. package/src/sap/base/util/restricted/_union.js +1 -1
  45. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  46. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  47. package/src/sap/base/util/restricted/_uniq.js +1 -1
  48. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  49. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  50. package/src/sap/base/util/restricted/_without.js +1 -1
  51. package/src/sap/base/util/restricted/_xor.js +1 -1
  52. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  53. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  54. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  55. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  56. package/src/sap/ui/Device.js +80 -168
  57. package/src/sap/ui/Global.js +4 -4
  58. package/src/sap/ui/VersionInfo.js +13 -10
  59. package/src/sap/ui/base/BindingParser.js +34 -7
  60. package/src/sap/ui/base/Event.js +1 -1
  61. package/src/sap/ui/base/EventProvider.js +1 -1
  62. package/src/sap/ui/base/ExpressionParser.js +1 -1
  63. package/src/sap/ui/base/Interface.js +1 -1
  64. package/src/sap/ui/base/ManagedObject.js +48 -27
  65. package/src/sap/ui/base/ManagedObjectMetadata.js +1 -1
  66. package/src/sap/ui/base/ManagedObjectObserver.js +2 -0
  67. package/src/sap/ui/base/Metadata.js +1 -1
  68. package/src/sap/ui/base/Object.js +1 -1
  69. package/src/sap/ui/base/ObjectPool.js +1 -1
  70. package/src/sap/ui/core/.library +2 -2
  71. package/src/sap/ui/core/BusyIndicator.js +1 -1
  72. package/src/sap/ui/core/BusyIndicatorUtils.js +1 -1
  73. package/src/sap/ui/core/Component.js +3 -3
  74. package/src/sap/ui/core/ComponentContainer.js +1 -1
  75. package/src/sap/ui/core/ComponentMetadata.js +2 -2
  76. package/src/sap/ui/core/ComponentSupport.js +1 -1
  77. package/src/sap/ui/core/Configuration.js +82 -15
  78. package/src/sap/ui/core/Control.js +3 -2
  79. package/src/sap/ui/core/Core.js +5 -6
  80. package/src/sap/ui/core/CustomData.js +1 -1
  81. package/src/sap/ui/core/DeclarativeSupport.js +1 -1
  82. package/src/sap/ui/core/Element.js +5 -7
  83. package/src/sap/ui/core/ElementMetadata.js +1 -1
  84. package/src/sap/ui/core/EnabledPropagator.js +1 -1
  85. package/src/sap/ui/core/EventBus.js +1 -1
  86. package/src/sap/ui/core/ExtensionPoint.js +1 -1
  87. package/src/sap/ui/core/FocusHandler.js +1 -1
  88. package/src/sap/ui/core/Fragment.js +1 -1
  89. package/src/sap/ui/core/HTML.js +1 -1
  90. package/src/sap/ui/core/HTMLRenderer.js +1 -1
  91. package/src/sap/ui/core/History.js +1 -1
  92. package/src/sap/ui/core/Icon.js +18 -5
  93. package/src/sap/ui/core/IconRenderer.js +1 -1
  94. package/src/sap/ui/core/IndicationColorSupport.js +1 -1
  95. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  96. package/src/sap/ui/core/InvisibleMessage.js +1 -1
  97. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  98. package/src/sap/ui/core/InvisibleText.js +1 -1
  99. package/src/sap/ui/core/Item.js +1 -1
  100. package/src/sap/ui/core/LabelEnablement.js +9 -2
  101. package/src/sap/ui/core/LayoutData.js +1 -1
  102. package/src/sap/ui/core/ListItem.js +1 -1
  103. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  104. package/src/sap/ui/core/LocalBusyIndicatorRenderer.js +2 -2
  105. package/src/sap/ui/core/LocalBusyIndicatorSupport.js +1 -1
  106. package/src/sap/ui/core/Locale.js +1 -1
  107. package/src/sap/ui/core/LocaleData.js +60 -6
  108. package/src/sap/ui/core/Manifest.js +1 -1
  109. package/src/sap/ui/core/Message.js +1 -1
  110. package/src/sap/ui/core/Patcher.js +3 -3
  111. package/src/sap/ui/core/Placeholder.js +28 -28
  112. package/src/sap/ui/core/Popup.js +12 -9
  113. package/src/sap/ui/core/RenderManager.js +1 -1
  114. package/src/sap/ui/core/Renderer.js +1 -1
  115. package/src/sap/ui/core/ResizeHandler.js +1 -1
  116. package/src/sap/ui/core/ScrollBar.js +1 -1
  117. package/src/sap/ui/core/ScrollBarRenderer.js +1 -1
  118. package/src/sap/ui/core/SeparatorItem.js +1 -1
  119. package/src/sap/ui/core/Title.js +1 -1
  120. package/src/sap/ui/core/TooltipBase.js +2 -2
  121. package/src/sap/ui/core/UIArea.js +1 -1
  122. package/src/sap/ui/core/UIComponent.js +1 -1
  123. package/src/sap/ui/core/UIComponentMetadata.js +1 -1
  124. package/src/sap/ui/core/ValueStateSupport.js +1 -1
  125. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  126. package/src/sap/ui/core/XMLComposite.js +1 -1
  127. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  128. package/src/sap/ui/core/XMLTemplateProcessor.js +7 -6
  129. package/src/sap/ui/core/_IconRegistry.js +13 -3
  130. package/src/sap/ui/core/cache/CacheManager.js +1 -1
  131. package/src/sap/ui/core/cache/LRUPersistentCache.js +2 -1
  132. package/src/sap/ui/core/cldr/en_AU.json +1 -1
  133. package/src/sap/ui/core/date/Buddhist.js +3 -3
  134. package/src/sap/ui/core/date/Japanese.js +4 -4
  135. package/src/sap/ui/core/date/UniversalDate.js +10 -0
  136. package/src/sap/ui/core/date/UniversalDateUtils.js +175 -5
  137. package/src/sap/ui/core/delegate/ItemNavigation.js +1 -1
  138. package/src/sap/ui/core/delegate/ScrollEnablement.js +9 -6
  139. package/src/sap/ui/core/dnd/DragAndDrop.js +21 -18
  140. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  141. package/src/sap/ui/core/dnd/DragDropInfo.js +1 -1
  142. package/src/sap/ui/core/dnd/DragInfo.js +1 -1
  143. package/src/sap/ui/core/dnd/DropInfo.js +3 -3
  144. package/src/sap/ui/core/format/DateFormat.js +654 -202
  145. package/src/sap/ui/core/format/DateFormatTimezoneDisplay.js +44 -0
  146. package/src/sap/ui/core/format/ListFormat.js +2 -2
  147. package/src/sap/ui/core/format/NumberFormat.js +502 -216
  148. package/src/sap/ui/core/format/TimezoneUtil.js +248 -0
  149. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  150. package/src/sap/ui/core/library.js +126 -53
  151. package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
  152. package/src/sap/ui/core/message/Message.js +1 -1
  153. package/src/sap/ui/core/message/MessageManager.js +1 -1
  154. package/src/sap/ui/core/message/MessageMixin.js +2 -1
  155. package/src/sap/ui/core/message/MessageParser.js +1 -1
  156. package/src/sap/ui/core/message/MessageProcessor.js +1 -1
  157. package/src/sap/ui/core/messagebundle.properties +2 -0
  158. package/src/sap/ui/core/messagebundle_ar.properties +1 -0
  159. package/src/sap/ui/core/messagebundle_bg.properties +6 -5
  160. package/src/sap/ui/core/messagebundle_ca.properties +1 -0
  161. package/src/sap/ui/core/messagebundle_cs.properties +1 -0
  162. package/src/sap/ui/core/messagebundle_cy.properties +1 -0
  163. package/src/sap/ui/core/messagebundle_da.properties +1 -0
  164. package/src/sap/ui/core/messagebundle_de.properties +2 -1
  165. package/src/sap/ui/core/messagebundle_el.properties +1 -0
  166. package/src/sap/ui/core/messagebundle_en.properties +1 -0
  167. package/src/sap/ui/core/messagebundle_en_GB.properties +1 -0
  168. package/src/sap/ui/core/messagebundle_en_US_sappsd.properties +1 -0
  169. package/src/sap/ui/core/messagebundle_en_US_saprigi.properties +1 -0
  170. package/src/sap/ui/core/messagebundle_en_US_saptrc.properties +1 -0
  171. package/src/sap/ui/core/messagebundle_es.properties +1 -0
  172. package/src/sap/ui/core/messagebundle_es_MX.properties +1 -0
  173. package/src/sap/ui/core/messagebundle_et.properties +1 -0
  174. package/src/sap/ui/core/messagebundle_fi.properties +1 -0
  175. package/src/sap/ui/core/messagebundle_fr.properties +1 -0
  176. package/src/sap/ui/core/messagebundle_fr_CA.properties +1 -0
  177. package/src/sap/ui/core/messagebundle_hi.properties +1 -0
  178. package/src/sap/ui/core/messagebundle_hr.properties +1 -0
  179. package/src/sap/ui/core/messagebundle_hu.properties +1 -0
  180. package/src/sap/ui/core/messagebundle_id.properties +3 -2
  181. package/src/sap/ui/core/messagebundle_it.properties +2 -1
  182. package/src/sap/ui/core/messagebundle_iw.properties +1 -0
  183. package/src/sap/ui/core/messagebundle_ja.properties +1 -0
  184. package/src/sap/ui/core/messagebundle_kk.properties +1 -0
  185. package/src/sap/ui/core/messagebundle_ko.properties +2 -1
  186. package/src/sap/ui/core/messagebundle_lt.properties +1 -0
  187. package/src/sap/ui/core/messagebundle_lv.properties +2 -1
  188. package/src/sap/ui/core/messagebundle_ms.properties +1 -0
  189. package/src/sap/ui/core/messagebundle_nl.properties +1 -0
  190. package/src/sap/ui/core/messagebundle_no.properties +5 -4
  191. package/src/sap/ui/core/messagebundle_pl.properties +1 -0
  192. package/src/sap/ui/core/messagebundle_pt.properties +1 -0
  193. package/src/sap/ui/core/messagebundle_pt_PT.properties +1 -0
  194. package/src/sap/ui/core/messagebundle_ro.properties +1 -0
  195. package/src/sap/ui/core/messagebundle_ru.properties +1 -0
  196. package/src/sap/ui/core/messagebundle_sh.properties +1 -0
  197. package/src/sap/ui/core/messagebundle_sk.properties +1 -0
  198. package/src/sap/ui/core/messagebundle_sl.properties +1 -0
  199. package/src/sap/ui/core/messagebundle_sv.properties +1 -0
  200. package/src/sap/ui/core/messagebundle_th.properties +1 -0
  201. package/src/sap/ui/core/messagebundle_tr.properties +1 -0
  202. package/src/sap/ui/core/messagebundle_uk.properties +1 -0
  203. package/src/sap/ui/core/messagebundle_vi.properties +1 -0
  204. package/src/sap/ui/core/messagebundle_zh_CN.properties +1 -0
  205. package/src/sap/ui/core/messagebundle_zh_TW.properties +1 -0
  206. package/src/sap/ui/core/mvc/Controller.js +1 -1
  207. package/src/sap/ui/core/mvc/ControllerExtensionProvider.js +1 -1
  208. package/src/sap/ui/core/mvc/HTMLView.js +1 -1
  209. package/src/sap/ui/core/mvc/HTMLViewRenderer.js +1 -1
  210. package/src/sap/ui/core/mvc/JSONView.js +2 -1
  211. package/src/sap/ui/core/mvc/JSONViewRenderer.js +1 -1
  212. package/src/sap/ui/core/mvc/JSView.js +1 -1
  213. package/src/sap/ui/core/mvc/JSViewRenderer.js +1 -1
  214. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  215. package/src/sap/ui/core/mvc/TemplateViewRenderer.js +1 -1
  216. package/src/sap/ui/core/mvc/View.js +2 -1
  217. package/src/sap/ui/core/mvc/ViewRenderer.js +1 -1
  218. package/src/sap/ui/core/mvc/XMLView.js +24 -3
  219. package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
  220. package/src/sap/ui/core/plugin/LessSupport.js +1 -1
  221. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  222. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  223. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  224. package/src/sap/ui/core/routing/Route.js +6 -6
  225. package/src/sap/ui/core/routing/Router.js +4 -3
  226. package/src/sap/ui/core/routing/Targets.js +17 -13
  227. package/src/sap/ui/core/rules/Misc.support.js +8 -3
  228. package/src/sap/ui/core/rules/Model.support.js +95 -8
  229. package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
  230. package/src/sap/ui/core/search/SearchProvider.js +1 -1
  231. package/src/sap/ui/core/service/Service.js +1 -1
  232. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  233. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  234. package/src/sap/ui/core/support/Plugin.js +1 -1
  235. package/src/sap/ui/core/support/Support.js +3 -3
  236. package/src/sap/ui/core/support/plugins/ControlTree.js +1 -1
  237. package/src/sap/ui/core/support/plugins/Interaction.js +1 -1
  238. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
  239. package/src/sap/ui/core/support/plugins/Performance.js +1 -1
  240. package/src/sap/ui/core/support/plugins/Selector.js +1 -1
  241. package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
  242. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  243. package/src/sap/ui/core/support/plugins/ViewInfo.js +1 -1
  244. package/src/sap/ui/core/support/techinfo/TechnicalInfo.js +1 -5
  245. package/src/sap/ui/core/themes/base/CommandShortcutHints.less +1 -1
  246. package/src/sap/ui/core/themes/base/base.less +1108 -35
  247. package/src/sap/ui/core/themes/base/fonts/SAP-icons.woff2 +0 -0
  248. package/src/sap/ui/core/themes/base/global.less +158 -4
  249. package/src/sap/ui/core/themes/base/parameterClasses.less +21 -21
  250. package/src/sap/ui/core/themes/sap_hcb/global.less +157 -2
  251. package/src/sap/ui/core/theming/Parameters.js +22 -142
  252. package/src/sap/ui/core/theming/ThemeHelper.js +26 -37
  253. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  254. package/src/sap/ui/core/tmpl/DOMElement.js +1 -1
  255. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  256. package/src/sap/ui/core/tmpl/Template.js +1 -1
  257. package/src/sap/ui/core/tmpl/TemplateControl.js +1 -1
  258. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  259. package/src/sap/ui/core/util/DraftEnabledMockServer.js +21 -16
  260. package/src/sap/ui/core/util/Export.js +1 -1
  261. package/src/sap/ui/core/util/ExportCell.js +1 -1
  262. package/src/sap/ui/core/util/ExportColumn.js +1 -1
  263. package/src/sap/ui/core/util/ExportRow.js +1 -1
  264. package/src/sap/ui/core/util/ExportType.js +1 -1
  265. package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
  266. package/src/sap/ui/core/util/File.js +1 -1
  267. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  268. package/src/sap/ui/core/util/MockServer.js +157 -57
  269. package/src/sap/ui/core/util/PasteHelper.js +5 -5
  270. package/src/sap/ui/core/util/XMLPreprocessor.js +17 -4
  271. package/src/sap/ui/core/util/reflection/BaseTreeModifier.js +4 -0
  272. package/src/sap/ui/core/util/reflection/JsControlTreeModifier.js +26 -16
  273. package/src/sap/ui/core/util/reflection/XmlTreeModifier.js +1 -1
  274. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
  275. package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
  276. package/src/sap/ui/core/util/serializer/ViewSerializer.js +1 -1
  277. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
  278. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  279. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  280. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  281. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  282. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  283. package/src/sap/ui/core/ws/WebSocket.js +1 -1
  284. package/src/sap/ui/debug/ControlTree.js +1 -1
  285. package/src/sap/ui/debug/DebugEnv.js +1 -1
  286. package/src/sap/ui/debug/LogViewer.js +2 -2
  287. package/src/sap/ui/debug/PropertyList.js +1 -1
  288. package/src/sap/ui/dom/includeStylesheet.js +8 -3
  289. package/src/sap/ui/events/jquery/EventExtension.js +1 -1
  290. package/src/sap/ui/events/jquery/EventSimulation.js +3 -13
  291. package/src/sap/ui/model/Binding.js +4 -3
  292. package/src/sap/ui/model/ClientModel.js +1 -1
  293. package/src/sap/ui/model/ClientTreeBinding.js +1 -1
  294. package/src/sap/ui/model/CompositeBinding.js +4 -1
  295. package/src/sap/ui/model/CompositeDataState.js +26 -4
  296. package/src/sap/ui/model/CompositeType.js +13 -1
  297. package/src/sap/ui/model/ContextBinding.js +1 -1
  298. package/src/sap/ui/model/DataState.js +27 -6
  299. package/src/sap/ui/model/ListBinding.js +2 -2
  300. package/src/sap/ui/model/MetaModel.js +2 -3
  301. package/src/sap/ui/model/Model.js +2 -2
  302. package/src/sap/ui/model/SelectionModel.js +1 -1
  303. package/src/sap/ui/model/SimpleType.js +1 -1
  304. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  305. package/src/sap/ui/model/Type.js +1 -1
  306. package/src/sap/ui/model/_Helper.js +22 -0
  307. package/src/sap/ui/model/analytics/AnalyticalBinding.js +68 -42
  308. package/src/sap/ui/model/analytics/ODataModelAdapter.js +2 -15
  309. package/src/sap/ui/model/base/ManagedObjectModel.js +9 -7
  310. package/src/sap/ui/model/json/JSONListBinding.js +1 -1
  311. package/src/sap/ui/model/json/JSONModel.js +15 -8
  312. package/src/sap/ui/model/json/JSONPropertyBinding.js +1 -1
  313. package/src/sap/ui/model/message/MessageListBinding.js +1 -1
  314. package/src/sap/ui/model/message/MessageModel.js +1 -1
  315. package/src/sap/ui/model/message/MessagePropertyBinding.js +1 -1
  316. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  317. package/src/sap/ui/model/odata/ODataListBinding.js +1 -1
  318. package/src/sap/ui/model/odata/ODataMessageParser.js +1 -1
  319. package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
  320. package/src/sap/ui/model/odata/ODataMetadata.js +3 -3
  321. package/src/sap/ui/model/odata/ODataModel.js +2 -2
  322. package/src/sap/ui/model/odata/ODataPropertyBinding.js +3 -1
  323. package/src/sap/ui/model/odata/ODataTreeBinding.js +1 -1
  324. package/src/sap/ui/model/odata/ODataTreeBindingFlat.js +1 -1
  325. package/src/sap/ui/model/odata/_AnnotationHelperBasics.js +1 -1
  326. package/src/sap/ui/model/odata/_AnnotationHelperExpression.js +1 -1
  327. package/src/sap/ui/model/odata/_ODataMetaModelUtils.js +1 -1
  328. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  329. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  330. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  331. package/src/sap/ui/model/odata/type/Date.js +1 -1
  332. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  333. package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
  334. package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
  335. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +346 -0
  336. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  337. package/src/sap/ui/model/odata/type/Double.js +1 -1
  338. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  339. package/src/sap/ui/model/odata/type/Int.js +1 -1
  340. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  341. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  342. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  343. package/src/sap/ui/model/odata/type/ODataType.js +1 -1
  344. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  345. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  346. package/src/sap/ui/model/odata/type/Single.js +1 -1
  347. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  348. package/src/sap/ui/model/odata/type/String.js +1 -1
  349. package/src/sap/ui/model/odata/type/Time.js +1 -1
  350. package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
  351. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  352. package/src/sap/ui/model/odata/type/UnitMixin.js +1 -1
  353. package/src/sap/ui/model/odata/v2/Context.js +62 -5
  354. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  355. package/src/sap/ui/model/odata/v2/ODataContextBinding.js +8 -4
  356. package/src/sap/ui/model/odata/v2/ODataListBinding.js +324 -112
  357. package/src/sap/ui/model/odata/v2/ODataModel.js +324 -94
  358. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +3 -4
  359. package/src/sap/ui/model/odata/v2/_CreatedContextsCache.js +65 -5
  360. package/src/sap/ui/model/odata/v4/AnnotationHelper.js +21 -22
  361. package/src/sap/ui/model/odata/v4/Context.js +224 -101
  362. package/src/sap/ui/model/odata/v4/ODataBinding.js +99 -55
  363. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +272 -210
  364. package/src/sap/ui/model/odata/v4/ODataListBinding.js +557 -258
  365. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +131 -100
  366. package/src/sap/ui/model/odata/v4/ODataModel.js +503 -260
  367. package/src/sap/ui/model/odata/v4/ODataParentBinding.js +106 -138
  368. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +87 -80
  369. package/src/sap/ui/model/odata/v4/ODataUtils.js +5 -5
  370. package/src/sap/ui/model/odata/v4/SubmitMode.js +0 -1
  371. package/src/sap/ui/model/odata/v4/ValueListType.js +0 -1
  372. package/src/sap/ui/model/odata/v4/_AnnotationHelperExpression.js +20 -20
  373. package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +3 -5
  374. package/src/sap/ui/model/odata/v4/lib/_AggregationHelper.js +5 -4
  375. package/src/sap/ui/model/odata/v4/lib/_Batch.js +21 -20
  376. package/src/sap/ui/model/odata/v4/lib/_Cache.js +322 -127
  377. package/src/sap/ui/model/odata/v4/lib/_GroupLock.js +5 -1
  378. package/src/sap/ui/model/odata/v4/lib/_Helper.js +28 -21
  379. package/src/sap/ui/model/odata/v4/lib/_MetadataConverter.js +62 -61
  380. package/src/sap/ui/model/odata/v4/lib/_MetadataRequestor.js +1 -1
  381. package/src/sap/ui/model/odata/v4/lib/_Parser.js +52 -43
  382. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +216 -51
  383. package/src/sap/ui/model/odata/v4/lib/_V2MetadataConverter.js +147 -147
  384. package/src/sap/ui/model/odata/v4/lib/_V2Requestor.js +14 -13
  385. package/src/sap/ui/model/odata/v4/lib/_V4MetadataConverter.js +66 -67
  386. package/src/sap/ui/model/resource/ResourceModel.js +1 -1
  387. package/src/sap/ui/model/resource/ResourcePropertyBinding.js +1 -1
  388. package/src/sap/ui/model/type/Boolean.js +1 -1
  389. package/src/sap/ui/model/type/Currency.js +1 -1
  390. package/src/sap/ui/model/type/Date.js +1 -1
  391. package/src/sap/ui/model/type/DateInterval.js +1 -1
  392. package/src/sap/ui/model/type/DateTime.js +1 -1
  393. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  394. package/src/sap/ui/model/type/FileSize.js +1 -1
  395. package/src/sap/ui/model/type/Float.js +1 -1
  396. package/src/sap/ui/model/type/Integer.js +1 -1
  397. package/src/sap/ui/model/type/String.js +1 -1
  398. package/src/sap/ui/model/type/Time.js +1 -1
  399. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  400. package/src/sap/ui/model/type/Unit.js +1 -1
  401. package/src/sap/ui/model/xml/XMLListBinding.js +1 -1
  402. package/src/sap/ui/model/xml/XMLModel.js +1 -1
  403. package/src/sap/ui/model/xml/XMLPropertyBinding.js +1 -1
  404. package/src/sap/ui/performance/trace/FESR.js +1 -1
  405. package/src/sap/ui/performance/trace/FESRHelper.js +72 -0
  406. package/src/sap/ui/performance/trace/Interaction.js +6 -2
  407. package/src/sap/ui/performance/trace/Passport.js +3 -3
  408. package/src/sap/ui/qunit/qunit-2-css.js +4 -4
  409. package/src/sap/ui/qunit/qunit-css.js +4 -4
  410. package/src/sap/ui/qunit/utils/ControlIterator.js +1 -1
  411. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +1 -1
  412. package/src/sap/ui/test/BlanketReporter.js +1 -1
  413. package/src/sap/ui/test/BranchTracking.js +1 -0
  414. package/src/sap/ui/test/Opa5.js +1 -1
  415. package/src/sap/ui/test/OpaBuilder.js +7 -7
  416. package/src/sap/ui/test/TestUtils.js +12 -2
  417. package/src/sap/ui/test/_LogCollector.js +1 -1
  418. package/src/sap/ui/test/_UsageReport.js +1 -1
  419. package/src/sap/ui/test/actions/Action.js +4 -2
  420. package/src/sap/ui/test/actions/Press.js +51 -2
  421. package/src/sap/ui/test/autowaiter/_XHRWaiter.js +1 -1
  422. package/src/sap/ui/test/generic/GenericTestCollection.js +176 -0
  423. package/src/sap/ui/test/generic/TestBase.js +151 -0
  424. package/src/sap/ui/test/generic/Utils.js +284 -0
  425. package/src/sap/ui/test/selectors/_ControlSelectorGenerator.js +9 -8
  426. package/src/sap/ui/test/selectors/_ControlSelectorValidator.js +1 -1
  427. package/src/sap/ui/test/starter/_setupAndStart.js +4 -0
  428. package/src/sap/ui/test/starter/createSuite.js +3 -3
  429. package/src/sap/ui/thirdparty/IPv6.js +1 -1
  430. package/src/sap/ui/thirdparty/SecondLevelDomains.js +1 -1
  431. package/src/sap/ui/thirdparty/URI.js +7 -3
  432. package/src/sap/ui/thirdparty/URITemplate.js +1 -1
  433. package/src/sap/ui/thirdparty/jquery-mobile-custom.js +3 -6
  434. package/src/sap/ui/thirdparty/jqueryui/jquery-ui-datepicker.js +143 -3
  435. package/src/sap/ui/thirdparty/jqueryui/jquery-ui-position.js +8 -1
  436. package/src/sap/ui/thirdparty/jszip.js +17 -7
  437. package/src/sap/ui/thirdparty/mobify-carousel.js +1 -1
  438. package/src/sap/ui/util/Mobile.js +17 -0
  439. package/src/sap/ui/util/Storage.js +1 -1
  440. package/src/sap/ui/util/XMLHelper.js +53 -30
  441. package/src/ui5loader.js +4 -4
@@ -131,26 +131,29 @@ sap.ui.define([
131
131
  /**
132
132
  * Deletes an entity on the server and in the cached data.
133
133
  *
134
- * @param {sap.ui.model.odata.v4.lib._GroupLock} oGroupLock
135
- * A lock for the group ID
134
+ * @param {sap.ui.model.odata.v4.lib._GroupLock} [oGroupLock]
135
+ * A lock for the group ID to be used for the DELETE request; w/o a lock, no DELETE is sent.
136
+ * For a transient entity, the lock is ignored (use NULL)!
136
137
  * @param {string} sEditUrl
137
- * The entity's edit URL
138
+ * The entity's edit URL to be used for the DELETE request; w/o a lock, this is mostly
139
+ * ignored.
138
140
  * @param {string} sPath
139
141
  * The entity's path within the cache (as used by change listeners)
140
142
  * @param {object} [oETagEntity]
141
143
  * An entity with the ETag of the binding for which the deletion was requested. This is
142
144
  * provided if the deletion is delegated from a context binding with empty path to a list
143
- * binding.
145
+ * binding. W/o a lock, this is ignored.
144
146
  * @param {boolean} [bDoNotRequestCount]
145
147
  * Whether not to request the new count from the server; useful in case of
146
148
  * {@link sap.ui.model.odata.v4.Context#replaceWith} where it is known that the count remains
147
- * unchanged
149
+ * unchanged; w/o a lock this should be true
148
150
  * @param {function} fnCallback
149
151
  * A function which is called after a transient entity has been deleted from the cache or
150
152
  * after the entity has been deleted from the server and from the cache; the index of the
151
- * entity and the entity list are passed as parameter
153
+ * entity and the entity list are both passed as parameter, or none of them
152
154
  * @returns {sap.ui.base.SyncPromise}
153
- * A promise for the DELETE request
155
+ * A promise which is resolved without a result in case of success, or rejected with an
156
+ * instance of <code>Error</code> in case of failure
154
157
  * @throws {Error} If the cache is shared
155
158
  *
156
159
  * @public
@@ -181,7 +184,6 @@ sap.ui.define([
181
184
  throw new Error("No 'delete' allowed while waiting for server response");
182
185
  }
183
186
  if (sTransientGroup) {
184
- oGroupLock.unlock();
185
187
  that.oRequestor.removePost(sTransientGroup, oEntity);
186
188
  return undefined;
187
189
  }
@@ -192,38 +194,38 @@ sap.ui.define([
192
194
  mHeaders = {"If-Match" : oETagEntity || oEntity};
193
195
  sEditUrl += that.oRequestor.buildQueryString(that.sMetaPath, that.mQueryOptions, true);
194
196
  return SyncPromise.all([
195
- that.oRequestor.request("DELETE", sEditUrl, oGroupLock.getUnlockedCopy(), mHeaders,
196
- undefined, undefined, undefined, undefined,
197
- _Helper.buildPath(that.getOriginalResourcePath(oEntity), sEntityPath))
198
- .catch(function (oError) {
199
- if (oError.status !== 404) {
200
- delete oEntity["$ui5.deleting"];
201
- throw oError;
202
- } // else: map 404 to 200
203
- })
204
- .then(function () {
205
- if (Array.isArray(vCacheData)) {
206
- fnCallback(
207
- that.removeElement(vCacheData, iIndex, sKeyPredicate, sParentPath),
208
- vCacheData);
209
- } else {
210
- if (vDeleteProperty) {
211
- // set to null and notify listeners
212
- _Helper.updateExisting(that.mChangeListeners, sParentPath,
213
- vCacheData, _Cache.makeUpdateData([vDeleteProperty], null));
214
- } else { // deleting at root level
215
- oEntity["$ui5.deleted"] = true;
216
- }
217
- fnCallback();
218
- }
219
- that.oRequestor.getModelInterface().reportStateMessages(that.sResourcePath,
220
- [], [sEntityPath]);
221
- }),
197
+ oGroupLock
198
+ && that.oRequestor.request("DELETE", sEditUrl, oGroupLock.getUnlockedCopy(),
199
+ mHeaders, undefined, undefined, undefined, undefined,
200
+ _Helper.buildPath(that.getOriginalResourcePath(oEntity), sEntityPath))
201
+ .catch(function (oError) {
202
+ if (oError.status !== 404) {
203
+ delete oEntity["$ui5.deleting"];
204
+ throw oError;
205
+ } // else: map 404 to 200
206
+ }),
222
207
  iIndex === undefined // single element or kept-alive not in list
223
208
  && !bDoNotRequestCount
224
209
  && that.requestCount(oGroupLock),
225
- oGroupLock.unlock() // unlock when all requests have been queued
226
- ]);
210
+ oGroupLock && oGroupLock.unlock() // unlock when all requests have been queued
211
+ ]).then(function () {
212
+ if (Array.isArray(vCacheData)) {
213
+ fnCallback(
214
+ that.removeElement(vCacheData, iIndex, sKeyPredicate, sParentPath),
215
+ vCacheData);
216
+ } else {
217
+ if (vDeleteProperty) {
218
+ // set to null and notify listeners
219
+ _Helper.updateExisting(that.mChangeListeners, sParentPath,
220
+ vCacheData, _Cache.makeUpdateData([vDeleteProperty], null));
221
+ } else { // deleting at root level
222
+ oEntity["$ui5.deleted"] = true;
223
+ }
224
+ fnCallback();
225
+ }
226
+ that.oRequestor.getModelInterface().reportStateMessages(that.sResourcePath,
227
+ {}, [sEntityPath]);
228
+ });
227
229
  }).finally(function () {
228
230
  that.removePendingRequest();
229
231
  });
@@ -258,7 +260,7 @@ sap.ui.define([
258
260
  * A map from meta path to the entity type (as delivered by {@link #fetchTypes})
259
261
  * @param {string} sMetaPath
260
262
  * The meta path for the entity
261
- * @returns {string}
263
+ * @returns {string|undefined}
262
264
  * The key predicate or <code>undefined</code>, if key predicate cannot be determined
263
265
  * @private
264
266
  */
@@ -290,7 +292,7 @@ sap.ui.define([
290
292
  };
291
293
 
292
294
  /**
293
- * Creates a transient entity at the front of the list and adds a POST request to the batch
295
+ * Creates a transient entity, inserts it in the list and adds a POST request to the batch
294
296
  * group with the given ID. If the POST request failed, <code>fnErrorCallback</code> is called
295
297
  * with an Error object, the POST request is automatically added again to the same batch
296
298
  * group (for SubmitMode.API) or parked (for SubmitMode.Auto or SubmitMode.Direct). Parked POST
@@ -306,6 +308,9 @@ sap.ui.define([
306
308
  * A (temporary) key predicate for the transient entity: "($uid=...)"
307
309
  * @param {string} [oEntityData={}]
308
310
  * The initial entity data
311
+ * @param {boolean} bAtEndOfCreated
312
+ * Whether the newly created entity should be inserted after previously created entities or at
313
+ * the front of the list.
309
314
  * @param {function} fnErrorCallback
310
315
  * A function which is called with an error object each time a POST request for the create
311
316
  * fails
@@ -319,8 +324,9 @@ sap.ui.define([
319
324
  * @public
320
325
  */
321
326
  _Cache.prototype.create = function (oGroupLock, oPostPathPromise, sPath, sTransientPredicate,
322
- oEntityData, fnErrorCallback, fnSubmitCallback) {
323
- var aCollection,
327
+ oEntityData, bAtEndOfCreated, fnErrorCallback, fnSubmitCallback) {
328
+ var aCollection = this.getValue(sPath),
329
+ sGroupId = oGroupLock.getGroupId(),
324
330
  bKeepTransientPath = oEntityData && oEntityData["@$ui5.keepTransientPath"],
325
331
  oPostBody,
326
332
  that = this;
@@ -330,10 +336,14 @@ sap.ui.define([
330
336
  _Helper.removeByPath(that.mPostRequests, sPath, oEntityData);
331
337
  aCollection.splice(aCollection.indexOf(oEntityData), 1);
332
338
  aCollection.$created -= 1;
333
- addToCount(that.mChangeListeners, sPath, aCollection, -1);
339
+ if (!oEntityData["@$ui5.context.isInactive"]) {
340
+ that.iActiveElements -= 1;
341
+ addToCount(that.mChangeListeners, sPath, aCollection, -1);
342
+ }
334
343
  delete aCollection.$byPredicate[sTransientPredicate];
335
344
  if (!sPath) {
336
345
  // Note: sPath is empty only in a CollectionCache, so we may call adjustReadRequests
346
+ // Note: index 0 is OK here (see "Must not request created element")
337
347
  that.adjustReadRequests(0, -1);
338
348
  }
339
349
  oGroupLock.cancel();
@@ -347,10 +357,8 @@ sap.ui.define([
347
357
  }
348
358
 
349
359
  function request(sPostPath, oPostGroupLock) {
350
- var sPostGroupId = oPostGroupLock.getGroupId();
351
-
352
360
  // mark as transient (again)
353
- _Helper.setPrivateAnnotation(oEntityData, "transient", sPostGroupId);
361
+ _Helper.setPrivateAnnotation(oEntityData, "transient", sGroupId);
354
362
  _Helper.addByPath(that.mPostRequests, sPath, oEntityData);
355
363
  return SyncPromise.all([
356
364
  that.oRequestor.request("POST", sPostPath, oPostGroupLock, null, oPostBody,
@@ -402,14 +410,22 @@ sap.ui.define([
402
410
  if (that.fetchTypes().isRejected()) {
403
411
  throw oError;
404
412
  }
405
- sPostGroupId = sPostGroupId.replace(rInactive, "");
406
- return request(sPostPath, that.oRequestor.lockGroup(
407
- that.oRequestor.getGroupSubmitMode(sPostGroupId) === "API" ?
408
- sPostGroupId : "$parked." + sPostGroupId, that, true, true));
413
+ sGroupId = sGroupId.replace(rInactive, "");
414
+ sGroupId = that.oRequestor.getGroupSubmitMode(sGroupId) === "API"
415
+ ? sGroupId
416
+ : "$parked." + sGroupId;
417
+
418
+ return request(sPostPath,
419
+ that.oRequestor.lockGroup(sGroupId, that, true, true));
409
420
  });
410
421
  }
411
422
 
412
423
  this.checkSharedRequest();
424
+ if (!Array.isArray(aCollection)) {
425
+ throw new Error("Create is only supported for collections; '" + sPath
426
+ + "' does not reference a collection");
427
+ }
428
+
413
429
  // clone data to avoid modifications outside the cache
414
430
  // remove any property starting with "@$ui5."
415
431
  oEntityData = _Helper.publicClone(oEntityData, true) || {};
@@ -418,15 +434,19 @@ sap.ui.define([
418
434
  _Helper.setPrivateAnnotation(oEntityData, "postBody", oPostBody);
419
435
  _Helper.setPrivateAnnotation(oEntityData, "transientPredicate", sTransientPredicate);
420
436
  oEntityData["@$ui5.context.isTransient"] = true;
437
+ if (sGroupId.startsWith("$inactive.")) {
438
+ oEntityData["@$ui5.context.isInactive"] = true;
439
+ } else {
440
+ this.iActiveElements += 1;
441
+ addToCount(this.mChangeListeners, sPath, aCollection, 1);
442
+ }
421
443
 
422
- aCollection = this.getValue(sPath);
423
- if (!Array.isArray(aCollection)) {
424
- throw new Error("Create is only supported for collections; '" + sPath
425
- + "' does not reference a collection");
444
+ if (bAtEndOfCreated) {
445
+ aCollection.splice(aCollection.$created, 0, oEntityData);
446
+ } else {
447
+ aCollection.unshift(oEntityData);
426
448
  }
427
- aCollection.unshift(oEntityData);
428
449
  aCollection.$created += 1;
429
- addToCount(this.mChangeListeners, sPath, aCollection, 1);
430
450
  // if the nested collection is empty $byPredicate is not available, create it on demand
431
451
  aCollection.$byPredicate = aCollection.$byPredicate || {};
432
452
  aCollection.$byPredicate[sTransientPredicate] = oEntityData;
@@ -634,7 +654,7 @@ sap.ui.define([
634
654
  * @param {string} sMissingPropertyPath
635
655
  * The path of the missing property relative to oResource; this property is returned so that
636
656
  * drillDown can proceed
637
- * @returns {sap.ui.base.SyncPromise}
657
+ * @returns {sap.ui.base.SyncPromise|undefined}
638
658
  * A promise resolving with the missing property value or <code>undefined</code> if the
639
659
  * requested property is not an expected late property; it rejects with an error if the GET
640
660
  * request failed, or if the key predicate or the ETag has changed
@@ -645,6 +665,7 @@ sap.ui.define([
645
665
  sRequestedPropertyPath, sMissingPropertyPath) {
646
666
  var sFullResourceMetaPath,
647
667
  sFullResourcePath,
668
+ sGroupId,
648
669
  sMergeBasePath, // full resource path plus custom query options
649
670
  oPromise,
650
671
  mQueryOptions,
@@ -673,7 +694,7 @@ sap.ui.define([
673
694
  oEntityType = that.fetchType(mTypeForMetaPath, sMetaPath).getResult();
674
695
  }
675
696
  if (sBasePath) {
676
- // Key properties, ETag and predicate must only be copied from the result for nested
697
+ // Key properties and predicate must only be copied from the result for nested
677
698
  // properties. The root property is already loaded and has them already. We check
678
699
  // that they are unchanged in this case.
679
700
  (oEntityType.$Key || []).forEach(function (vKey) {
@@ -682,9 +703,10 @@ sap.ui.define([
682
703
  }
683
704
  aUpdateProperties.push(_Helper.buildPath(sBasePath, vKey));
684
705
  });
685
- aUpdateProperties.push(sBasePath + "/@odata.etag");
686
706
  aUpdateProperties.push(sBasePath + "/@$ui5._/predicate");
687
707
  }
708
+ // Always copy the ETag for the case that the cached entity is still initial
709
+ aUpdateProperties.push(_Helper.buildPath(sBasePath, "@odata.etag"));
688
710
  if (mQueryOptions0.$expand) {
689
711
  // intersecting the query options with sRequestedPropertyPath delivers exactly one
690
712
  // entry in $expand at each level (one for each navigation property binding)
@@ -720,7 +742,9 @@ sap.ui.define([
720
742
  // allow merge
721
743
  sMergeBasePath = sFullResourcePath
722
744
  + this.oRequestor.buildQueryString(sFullResourceMetaPath, this.mQueryOptions, true);
723
- oPromise = this.oRequestor.request("GET", sMergeBasePath, oGroupLock.getUnlockedCopy(),
745
+ sGroupId = _Helper.getPrivateAnnotation(oResource, "groupId");
746
+ oPromise = this.oRequestor.request("GET", sMergeBasePath,
747
+ sGroupId ? this.oRequestor.lockGroup(sGroupId, this) : oGroupLock.getUnlockedCopy(),
724
748
  undefined, undefined, undefined, undefined, sFullResourceMetaPath, undefined,
725
749
  false, mQueryOptions
726
750
  ).then(function (oData) {
@@ -740,7 +764,8 @@ sap.ui.define([
740
764
  throw new Error("GET " + sRequestPath + ": Key predicate changed from "
741
765
  + _Helper.getPrivateAnnotation(oResource, "predicate") + " to " + sPredicate);
742
766
  }
743
- if (oData["@odata.etag"] !== oResource["@odata.etag"]) {
767
+ // we expect the server to always or never send an ETag for this entity
768
+ if (oResource["@odata.etag"] && oData["@odata.etag"] !== oResource["@odata.etag"]) {
744
769
  throw new Error("GET " + sRequestPath + ": ETag changed");
745
770
  }
746
771
 
@@ -811,7 +836,8 @@ sap.ui.define([
811
836
  * @private
812
837
  */
813
838
  _Cache.prototype.fetchTypes = function () {
814
- var aPromises, mTypeForMetaPath, that = this;
839
+ var aPromises, mTypeForMetaPath,
840
+ that = this;
815
841
 
816
842
  /*
817
843
  * Recursively calls fetchType for all (sub)paths in $expand.
@@ -872,6 +898,24 @@ sap.ui.define([
872
898
  * @public
873
899
  */
874
900
 
901
+ /**
902
+ * Returns an array containing all current elements of a collection or single cache for the
903
+ * given relative path. If there are pending requests, the corresponding promises will be
904
+ * ignored and set to <code>undefined</code>.
905
+ *
906
+ * @param {string} [sPath]
907
+ * Relative path to drill-down into, may be empty (only for collection cache)
908
+ * @returns {object[]} The cache elements
909
+ */
910
+ _Cache.prototype.getAllElements = function (sPath) {
911
+ if (sPath) {
912
+ return this.getValue(sPath);
913
+ }
914
+ return this.aElements.map(function (oElement) {
915
+ return oElement instanceof SyncPromise ? undefined : oElement;
916
+ });
917
+ };
918
+
875
919
  /**
876
920
  * Returns the query options to be used for downloading list data corresponding to the given
877
921
  * query options.
@@ -947,6 +991,7 @@ sap.ui.define([
947
991
  *
948
992
  * @public
949
993
  */
994
+ // eslint-disable-next-line valid-jsdoc -- in the subclasses the function does return a value
950
995
  _Cache.prototype.getValue = function (_sPath) {
951
996
  throw new Error("Unsupported operation");
952
997
  };
@@ -999,13 +1044,18 @@ sap.ui.define([
999
1044
  * The relative path of a binding; must not end with '/'
1000
1045
  * @param {boolean} [bIgnoreKeptAlive]
1001
1046
  * Whether to ignore changes which will not be lost by APIs like sort or filter because they
1002
- * relate to a context which is kept alive.
1047
+ * relate to a context which is kept alive
1048
+ * @param {boolean} [bIgnoreTransient]
1049
+ * Whether to ignore transient elements on top level which will not be lost by APIs like sort
1050
+ * or filter
1003
1051
  * @returns {boolean}
1004
1052
  * <code>true</code> if there are pending changes
1005
1053
  *
1006
1054
  * @public
1055
+ * @see _CollectionCache#reset
1007
1056
  */
1008
- _Cache.prototype.hasPendingChangesForPath = function (sPath, bIgnoreKeptAlive) {
1057
+ _Cache.prototype.hasPendingChangesForPath = function (sPath, bIgnoreKeptAlive,
1058
+ bIgnoreTransient) {
1009
1059
  var that = this;
1010
1060
 
1011
1061
  return Object.keys(this.mPatchRequests).some(function (sRequestPath) {
@@ -1015,7 +1065,12 @@ sap.ui.define([
1015
1065
  return oPatchPromise.$isKeepAlive();
1016
1066
  }));
1017
1067
  }) || Object.keys(this.mPostRequests).some(function (sRequestPath) {
1018
- return isSubPath(sRequestPath, sPath);
1068
+ return bIgnoreTransient && !sRequestPath
1069
+ ? false // ignore transient elements on top level
1070
+ : isSubPath(sRequestPath, sPath)
1071
+ && that.mPostRequests[sRequestPath].some(function (oEntityData) {
1072
+ return !oEntityData["@$ui5.context.isInactive"];
1073
+ });
1019
1074
  });
1020
1075
  };
1021
1076
 
@@ -1178,9 +1233,9 @@ sap.ui.define([
1178
1233
  oEntity = aElements.$byPredicate[sPredicate];
1179
1234
  }
1180
1235
  sKeyFilter = _Helper.getKeyFilter(oEntity, that.sMetaPath, mTypeForMetaPath);
1181
- sInCollectionFilter =
1182
- (mQueryOptions.$filter ? "(" + mQueryOptions.$filter + ") and " : "")
1183
- + sKeyFilter;
1236
+ sInCollectionFilter
1237
+ = (mQueryOptions.$filter ? "(" + mQueryOptions.$filter + ") and " : "")
1238
+ + sKeyFilter;
1184
1239
  delete mQueryOptions.$count;
1185
1240
  delete mQueryOptions.$orderby;
1186
1241
 
@@ -1237,7 +1292,7 @@ sap.ui.define([
1237
1292
  } else if (aReadResult.length === 0) {
1238
1293
  that.removeElement(aElements, iIndex, sPredicate, sPath);
1239
1294
  that.oRequestor.getModelInterface()
1240
- .reportStateMessages(that.sResourcePath, [], [sPath + sPredicate]);
1295
+ .reportStateMessages(that.sResourcePath, {}, [sPath + sPredicate]);
1241
1296
  fnOnRemove(false);
1242
1297
  } else if (bRemoveFromCollection) {
1243
1298
  that.removeElement(aElements, iIndex, sPredicate, sPath);
@@ -1271,7 +1326,7 @@ sap.ui.define([
1271
1326
  /**
1272
1327
  * Removes the element at the given index from the given array, taking care of
1273
1328
  * <code>$byPredicate</code>, <code>$created</code>, the array's count, and a collection cache's
1274
- * limit (if applicable).
1329
+ * limit and number of active elements (if applicable).
1275
1330
  *
1276
1331
  * @param {object[]} aElements
1277
1332
  * The array of elements
@@ -1282,7 +1337,7 @@ sap.ui.define([
1282
1337
  * The key predicate of the old element to be removed
1283
1338
  * @param {string} sPath
1284
1339
  * The element collection's path within this cache (as used by change listeners), may be
1285
- * <code>""</code>
1340
+ * <code>""</code> (only in a CollectionCache)
1286
1341
  * @returns {number} The index at which the element actually was (it might have moved due to
1287
1342
  * parallel insert/delete)
1288
1343
  *
@@ -1303,14 +1358,18 @@ sap.ui.define([
1303
1358
  sTransientPredicate = _Helper.getPrivateAnnotation(oElement, "transientPredicate");
1304
1359
  if (sTransientPredicate) {
1305
1360
  aElements.$created -= 1;
1361
+ if (!sPath) {
1362
+ this.iActiveElements -= 1;
1363
+ }
1306
1364
  delete aElements.$byPredicate[sTransientPredicate];
1307
- } else if (!sPath) {
1365
+ }
1366
+ if (!sPath && iIndex !== undefined) {
1308
1367
  // Note: sPath is empty only in a CollectionCache, so we may use iLmit and
1309
1368
  // adjustReadRequests
1310
- if (iIndex !== undefined) {
1369
+ if (!sTransientPredicate) {
1311
1370
  this.iLimit -= 1; // this doesn't change Infinity
1312
- this.adjustReadRequests(iIndex, -1);
1313
1371
  }
1372
+ this.adjustReadRequests(iIndex, -1);
1314
1373
  }
1315
1374
  return iIndex;
1316
1375
  };
@@ -1369,7 +1428,7 @@ sap.ui.define([
1369
1428
  mTypeForMetaPath, sPath) {
1370
1429
  var oOldElement, sTransientPredicate;
1371
1430
 
1372
- if (iIndex === undefined) {// kept-alive element not in the list
1431
+ if (iIndex === undefined) { // kept-alive element not in the list
1373
1432
  aElements.$byPredicate[sPredicate] = oElement;
1374
1433
  } else {
1375
1434
  // the element might have moved due to parallel insert/delete
@@ -1394,13 +1453,15 @@ sap.ui.define([
1394
1453
  *
1395
1454
  * @param {sap.ui.model.odata.v4.lib._GroupLock} oGroupLock
1396
1455
  * A lock for the group ID
1397
- * @returns {Promise}
1398
- * A promise that resolves if the count has been determined or undefined if no request needed
1456
+ * @returns {Promise|undefined}
1457
+ * A promise that resolves if the count has been determined or <code>undefined</code> if no
1458
+ * request needed
1399
1459
  *
1400
1460
  * @private
1401
1461
  */
1402
1462
  _Cache.prototype.requestCount = function (oGroupLock) {
1403
- var sExclusiveFilter, mQueryOptions, sReadUrl, that = this;
1463
+ var sExclusiveFilter, mQueryOptions, sReadUrl,
1464
+ that = this;
1404
1465
 
1405
1466
  if (this.mQueryOptions && this.mQueryOptions.$count) {
1406
1467
  // now we are definitely in a CollectionCache
@@ -1427,7 +1488,7 @@ sap.ui.define([
1427
1488
  }
1428
1489
  throw oError;
1429
1490
  }).then(function (oResult) {
1430
- var iCount = parseInt(oResult["@odata.count"]) + that.aElements.$created;
1491
+ var iCount = parseInt(oResult["@odata.count"]) + that.iActiveElements;
1431
1492
 
1432
1493
  setCount(that.mChangeListeners, "", that.aElements, iCount);
1433
1494
  that.iLimit = iCount;
@@ -1468,9 +1529,11 @@ sap.ui.define([
1468
1529
  aEntities = that.mPostRequests[sRequestPath];
1469
1530
  for (i = aEntities.length - 1; i >= 0; i -= 1) {
1470
1531
  sTransientGroup = _Helper.getPrivateAnnotation(aEntities[i], "transient");
1471
- that.oRequestor.removePost(sTransientGroup, aEntities[i]);
1532
+ if (!sTransientGroup.startsWith("$inactive.")) {
1533
+ // this also cleans up that.mPostRequests
1534
+ that.oRequestor.removePost(sTransientGroup, aEntities[i]);
1535
+ }
1472
1536
  }
1473
- delete that.mPostRequests[sRequestPath];
1474
1537
  }
1475
1538
  });
1476
1539
  };
@@ -1794,13 +1857,18 @@ sap.ui.define([
1794
1857
  }
1795
1858
  // remember the old value
1796
1859
  vOldValue = _Helper.drillDown(oEntity, aPropertyPath);
1797
- // write the changed value into the cache
1798
- _Helper.updateAll(that.mChangeListeners, sEntityPath, oEntity, oUpdateData);
1799
1860
  oPostBody = _Helper.getPrivateAnnotation(oEntity, "postBody");
1800
1861
  if (oPostBody) {
1801
- // change listeners are already informed
1862
+ // change listeners are informed later
1802
1863
  _Helper.updateAll({}, sEntityPath, oPostBody, oUpdateData);
1864
+ if (oEntity["@$ui5.context.isInactive"]) {
1865
+ oUpdateData["@$ui5.context.isInactive"] = false;
1866
+ that.iActiveElements += 1;
1867
+ addToCount(that.mChangeListeners, "", that.aElements, 1);
1868
+ }
1803
1869
  }
1870
+ // write the changed value into the cache
1871
+ _Helper.updateAll(that.mChangeListeners, sEntityPath, oEntity, oUpdateData);
1804
1872
  if (sUnitOrCurrencyPath) {
1805
1873
  aUnitOrCurrencyPath = sUnitOrCurrencyPath.split("/");
1806
1874
  sUnitOrCurrencyPath = _Helper.buildPath(sEntityPath, sUnitOrCurrencyPath);
@@ -1838,7 +1906,7 @@ sap.ui.define([
1838
1906
  * predicates for all entities in the result. Collects and reports OData messages via
1839
1907
  * {@link sap.ui.model.odata.v4.lib._Requestor#reportStateMessages}.
1840
1908
  *
1841
- * @param {*} oRoot An OData response, arrays or simple values are wrapped into an object as
1909
+ * @param {any} oRoot An OData response, arrays or simple values are wrapped into an object as
1842
1910
  * property "value"
1843
1911
  * @param {object} mTypeForMetaPath A map from absolute meta path to entity type (as delivered
1844
1912
  * by {@link #fetchTypes})
@@ -1896,7 +1964,7 @@ sap.ui.define([
1896
1964
  * Calls visitInstance for all object entries of the given collection and creates the map
1897
1965
  * $byPredicate from predicate to entity.
1898
1966
  *
1899
- * @param {*[]} aInstances The collection
1967
+ * @param {any[]} aInstances The collection
1900
1968
  * @param {string} sMetaPath The meta path of the collection in mTypeForMetaPath
1901
1969
  * @param {string} sCollectionPath The path of the collection
1902
1970
  * @param {string} sContextUrl The context URL for message longtexts
@@ -2046,11 +2114,14 @@ sap.ui.define([
2046
2114
  return sDeepResourcePath;
2047
2115
  }, bSharedRequest);
2048
2116
 
2117
+ this.iActiveElements = 0; // number of active (client-side) created elements
2118
+ this.oBackup = null; // see #reset
2049
2119
  this.sContext = undefined; // the "@odata.context" from the responses
2050
2120
  this.aElements = []; // the available elements
2051
2121
  this.aElements.$byPredicate = {};
2052
2122
  this.aElements.$count = undefined; // see setCount
2053
- this.aElements.$created = 0; // number of (client-side) created elements
2123
+ // number of all (client-side) created elements (active or inactive)
2124
+ this.aElements.$created = 0;
2054
2125
  this.aElements.$tail = undefined; // promise for a read w/o $top
2055
2126
  // upper limit for @odata.count, maybe sharp; assumes #getQueryString can $filter out all
2056
2127
  // created elements
@@ -2095,6 +2166,24 @@ sap.ui.define([
2095
2166
  });
2096
2167
  };
2097
2168
 
2169
+ /**
2170
+ * Creates an empty element for the given predicate to the cache, adds it to the cache and
2171
+ * returns it.
2172
+ *
2173
+ * @param {string} sPredicate - The predicate
2174
+ * @returns {object} The empty element
2175
+ *
2176
+ * @public
2177
+ */
2178
+ _CollectionCache.prototype.createEmptyElement = function (sPredicate) {
2179
+ var oElement = {};
2180
+
2181
+ _Helper.setPrivateAnnotation(oElement, "predicate", sPredicate);
2182
+ this.aElements.$byPredicate[sPredicate] = oElement;
2183
+
2184
+ return oElement;
2185
+ };
2186
+
2098
2187
  /**
2099
2188
  * Replaces the old element at the given index with the given new element.
2100
2189
  *
@@ -2197,13 +2286,13 @@ sap.ui.define([
2197
2286
  for (i = iStart; i < iEnd; i += 1) {
2198
2287
  this.aElements[i] = oPromise;
2199
2288
  }
2200
- this.oSyncPromiseAll = undefined; // from now on, fetchValue has to wait again
2289
+ this.oSyncPromiseAll = undefined; // from now on, fetchValue has to wait again
2201
2290
  };
2202
2291
 
2203
2292
  /**
2204
2293
  * Returns a filter that excludes all created entities in this cache's collection.
2205
2294
  *
2206
- * @returns {string}
2295
+ * @returns {string|undefined}
2207
2296
  * The filter or <code>undefined</code> if there is no created entity.
2208
2297
  *
2209
2298
  * @private
@@ -2227,7 +2316,7 @@ sap.ui.define([
2227
2316
  }
2228
2317
  }
2229
2318
 
2230
- return aKeyFilters.length ? "not (" + aKeyFilters.join(" or ") + ")" : undefined;
2319
+ return aKeyFilters.length ? "not (" + aKeyFilters.sort().join(" or ") + ")" : undefined;
2231
2320
  };
2232
2321
 
2233
2322
  /**
@@ -2266,7 +2355,8 @@ sap.ui.define([
2266
2355
  * The start index of the range
2267
2356
  * @param {number} iEnd
2268
2357
  * The index after the last element
2269
- * @returns {string} The resource path including the query string
2358
+ * @returns {string}
2359
+ * The resource path including the query string
2270
2360
  * @throws {Error}
2271
2361
  * If there are created elements inside the given range
2272
2362
  *
@@ -2319,11 +2409,12 @@ sap.ui.define([
2319
2409
  * @private
2320
2410
  */
2321
2411
  _CollectionCache.prototype.handleResponse = function (iStart, iEnd, oResult, mTypeForMetaPath) {
2322
- var iCount = -1,
2323
- sCount,
2412
+ var sCount,
2324
2413
  iCreated = this.aElements.$created,
2325
2414
  oElement,
2326
2415
  oKeptElement,
2416
+ iLimit = -1,
2417
+ iOffset = 0,
2327
2418
  iOld$count = this.aElements.$count,
2328
2419
  sPredicate,
2329
2420
  iResultLength = oResult.value.length,
@@ -2337,7 +2428,14 @@ sap.ui.define([
2337
2428
  if (sPredicate) {
2338
2429
  oKeptElement = this.aElements.$byPredicate[sPredicate];
2339
2430
  if (oKeptElement) {
2340
- if (oElement["@odata.etag"] === oKeptElement["@odata.etag"]) {
2431
+ // we expect the server to always or never send an ETag for this entity
2432
+ if (!oKeptElement["@odata.etag"]
2433
+ || oElement["@odata.etag"] === oKeptElement["@odata.etag"]) {
2434
+ if (_Helper.hasPrivateAnnotation(oKeptElement, "transientPredicate")) {
2435
+ // client-side filter for newly created persisted
2436
+ iOffset += 1;
2437
+ continue;
2438
+ }
2341
2439
  _Helper.updateNonExisting(oKeptElement, oElement);
2342
2440
  oElement = oKeptElement;
2343
2441
  } else if (this.hasPendingChangesForPath(sPredicate)) {
@@ -2347,11 +2445,15 @@ sap.ui.define([
2347
2445
  }
2348
2446
  this.aElements.$byPredicate[sPredicate] = oElement;
2349
2447
  }
2350
- this.aElements[iStart + i] = oElement;
2448
+ this.aElements[iStart + i - iOffset] = oElement;
2351
2449
  }
2450
+ // simulate #getFilterExcludingCreated for newly created persisted
2451
+ iEnd -= iOffset;
2452
+ iResultLength -= iOffset;
2453
+
2352
2454
  sCount = oResult["@odata.count"];
2353
2455
  if (sCount) {
2354
- this.iLimit = iCount = parseInt(sCount);
2456
+ this.iLimit = iLimit = parseInt(sCount);
2355
2457
  }
2356
2458
  if (oResult["@odata.nextLink"]) { // server-driven paging
2357
2459
  this.bServerDrivenPaging = true;
@@ -2363,25 +2465,26 @@ sap.ui.define([
2363
2465
  this.aElements.length = iStart + iResultLength;
2364
2466
  }
2365
2467
  } else if (iResultLength < iEnd - iStart) { // short read
2366
- if (iCount === -1) {
2468
+ if (iLimit === -1) {
2367
2469
  // use formerly computed $count
2368
- iCount = iOld$count && iOld$count - iCreated;
2470
+ iLimit = iOld$count && iOld$count - this.iActiveElements;
2369
2471
  }
2370
- iCount = Math.min(
2371
- iCount !== undefined ? iCount : Infinity,
2472
+ iLimit = Math.min(
2473
+ iLimit !== undefined ? iLimit : Infinity,
2474
+ // length determined from the short read
2372
2475
  iStart - iCreated + iResultLength);
2373
- this.aElements.length = iCreated + iCount;
2374
- this.iLimit = iCount;
2476
+ this.aElements.length = iCreated + iLimit;
2477
+ this.iLimit = iLimit;
2375
2478
  // If the server did not send a count, the calculated count is greater than 0
2376
2479
  // and the element before has not been read yet, we do not know the count:
2377
2480
  // The element might or might not exist.
2378
- if (!sCount && iCount > 0 && !this.aElements[iCount - 1]) {
2379
- iCount = undefined;
2481
+ if (!sCount && iLimit > 0 && !this.aElements[iLimit - 1]) {
2482
+ iLimit = undefined;
2380
2483
  }
2381
2484
  }
2382
- if (iCount !== -1) {
2485
+ if (iLimit !== -1) {
2383
2486
  setCount(this.mChangeListeners, "", this.aElements,
2384
- iCount !== undefined ? iCount + iCreated : undefined);
2487
+ iLimit !== undefined ? iLimit + this.iActiveElements : undefined);
2385
2488
  }
2386
2489
  };
2387
2490
 
@@ -2420,7 +2523,9 @@ sap.ui.define([
2420
2523
  _CollectionCache.prototype.read = function (iIndex, iLength, iPrefetchLength, oGroupLock,
2421
2524
  fnDataRequested) {
2422
2525
  var aElementsRange,
2526
+ iEnd,
2423
2527
  oPromise = this.oPendingRequestsPromise || this.aElements.$tail,
2528
+ iTransientElements,
2424
2529
  that = this;
2425
2530
 
2426
2531
  if (iIndex < 0) {
@@ -2436,6 +2541,15 @@ sap.ui.define([
2436
2541
  });
2437
2542
  }
2438
2543
 
2544
+ // prepare for client-side filter for newly created persisted (see #handleResponse)
2545
+ iTransientElements = this.aElements.slice(0, this.aElements.$created)
2546
+ .filter(function (oElement) {
2547
+ return _Helper.getPrivateAnnotation(oElement, "transient")
2548
+ === oGroupLock.getGroupId();
2549
+ })
2550
+ .length;
2551
+ iPrefetchLength = Math.max(iPrefetchLength, iTransientElements);
2552
+
2439
2553
  ODataUtils._getReadIntervals(this.aElements, iIndex, iLength,
2440
2554
  this.bServerDrivenPaging ? 0 : iPrefetchLength,
2441
2555
  this.aElements.$created + this.iLimit)
@@ -2447,8 +2561,9 @@ sap.ui.define([
2447
2561
 
2448
2562
  oGroupLock.unlock();
2449
2563
 
2450
- aElementsRange = this.aElements.slice(iIndex, iIndex + iLength + iPrefetchLength);
2451
- if (this.aElements.$tail && iIndex + iLength > this.aElements.length) {
2564
+ iEnd = iIndex + iLength + iPrefetchLength;
2565
+ aElementsRange = this.aElements.slice(iIndex, iEnd);
2566
+ if (this.aElements.$tail && iEnd > this.aElements.length) {
2452
2567
  aElementsRange.push(this.aElements.$tail);
2453
2568
  }
2454
2569
  return SyncPromise.all(aElementsRange).then(function () {
@@ -2465,22 +2580,25 @@ sap.ui.define([
2465
2580
 
2466
2581
  /**
2467
2582
  * Refreshes the kept-alive elements. This needs to be called before the cache has filled the
2468
- * collection. In that state the $byPredicate contains only the kept-alive elements.
2583
+ * collection. In that state the $byPredicate contains only the kept-alive and created elements.
2469
2584
  *
2470
2585
  * @param {sap.ui.model.odata.v4.lib._GroupLock} oGroupLock
2471
2586
  * A lock for the group ID
2472
- * @param {function} fnOnRemove
2473
- * A function which is called if a kept-alive element does no longer exist
2474
- * @returns {sap.ui.base.SyncPromise}
2587
+ * @param {function(string,number)} fnOnRemove
2588
+ * A function which is called with predicate and index if a kept-alive or created element does
2589
+ * no longer exist after refresh; the index is undefined for a non-created element
2590
+ * @returns {sap.ui.base.SyncPromise|undefined}
2475
2591
  * A promise resolving without a defined result, or rejecting with an error if the refresh
2476
2592
  * fails, or <code>undefined</code> if there are no kept-alive elements.
2477
2593
  *
2478
2594
  * @public
2479
2595
  */
2480
2596
  _CollectionCache.prototype.refreshKeptElements = function (oGroupLock, fnOnRemove) {
2481
- var aPredicates = Object.keys(this.aElements.$byPredicate).sort(),
2482
- mTypes,
2483
- that = this;
2597
+ var that = this,
2598
+ // Note: at this time only kept-alive and created elements are in the cache, but we
2599
+ // don't care if $byPredicate still contains two entries for the same element
2600
+ aPredicates = Object.keys(this.aElements.$byPredicate).filter(isRefreshNeeded).sort(),
2601
+ mTypes;
2484
2602
 
2485
2603
  /*
2486
2604
  * Calculates a query to request the kept-alive elements.
@@ -2499,7 +2617,6 @@ sap.ui.define([
2499
2617
  delete mQueryOptions.$orderby;
2500
2618
  delete mQueryOptions.$search;
2501
2619
 
2502
- // Note: at this time only kept-alive elements are in the cache
2503
2620
  aKeyFilters = aPredicates.map(function (sPredicate) {
2504
2621
  return _Helper.getKeyFilter(that.aElements.$byPredicate[sPredicate], that.sMetaPath,
2505
2622
  mTypes);
@@ -2514,6 +2631,20 @@ sap.ui.define([
2514
2631
  + that.oRequestor.buildQueryString(that.sMetaPath, mQueryOptions, false, true);
2515
2632
  }
2516
2633
 
2634
+ /*
2635
+ * Tells whether a refresh is needed for the given predicate. Transient predicates and
2636
+ * elements with pending changes need no refresh.
2637
+ *
2638
+ * @param {string} sPredicate - A key predicate
2639
+ * @returns {boolean} - Whether a refresh is needed
2640
+ */
2641
+ function isRefreshNeeded(sPredicate) {
2642
+ var oElement = that.aElements.$byPredicate[sPredicate];
2643
+
2644
+ return _Helper.getPrivateAnnotation(oElement, "predicate") === sPredicate
2645
+ && !that.hasPendingChangesForPath(sPredicate);
2646
+ }
2647
+
2517
2648
  if (aPredicates.length === 0) {
2518
2649
  return undefined;
2519
2650
  }
@@ -2528,13 +2659,20 @@ sap.ui.define([
2528
2659
  mStillAliveElements = oResponse.value.$byPredicate || {};
2529
2660
 
2530
2661
  aPredicates.forEach(function (sPredicate) {
2662
+ var oElement, iIndex;
2663
+
2531
2664
  if (sPredicate in mStillAliveElements) {
2532
2665
  _Helper.updateAll(that.mChangeListeners, sPredicate,
2533
2666
  that.aElements.$byPredicate[sPredicate],
2534
2667
  mStillAliveElements[sPredicate]);
2535
2668
  } else {
2536
- delete that.aElements.$byPredicate[sPredicate];
2537
- fnOnRemove(sPredicate);
2669
+ oElement = that.aElements.$byPredicate[sPredicate];
2670
+ if (_Helper.getPrivateAnnotation(oElement, "transientPredicate")) {
2671
+ iIndex = that.removeElement(that.aElements, -1, sPredicate, "");
2672
+ } else {
2673
+ delete that.aElements.$byPredicate[sPredicate];
2674
+ }
2675
+ fnOnRemove(sPredicate, iIndex);
2538
2676
  }
2539
2677
  });
2540
2678
  });
@@ -2702,7 +2840,7 @@ sap.ui.define([
2702
2840
 
2703
2841
  return this.oRequestor.request("GET", sResourcePath, oGroupLock, undefined, undefined,
2704
2842
  undefined, undefined, this.sMetaPath, undefined, false, mMergeableQueryOptions,
2705
- function (aOtherPaths) {
2843
+ this, function (aOtherPaths) {
2706
2844
  if (arguments.length) {
2707
2845
  aPaths = aPaths.concat(aOtherPaths);
2708
2846
  } else {
@@ -2743,24 +2881,55 @@ sap.ui.define([
2743
2881
 
2744
2882
  /**
2745
2883
  * Resets this cache to its initial state, but keeps certain elements and their change listeners
2746
- * alive.
2884
+ * alive: all kept-alive elements identified by the given key predicates as well as all
2885
+ * transient elements on top level.
2747
2886
  *
2748
2887
  * @param {string[]} aKeptElementPredicates
2749
2888
  * The key predicates for all kept-alive elements
2889
+ * @param {boolean} [bKeepCreated]
2890
+ * Whether created persisted elements that started as inactive shall be kept in place and a
2891
+ * backup shall be remembered for a later {@link #restore}
2750
2892
  *
2751
2893
  * @public
2894
+ * @see _Cache#hasPendingChangesForPath
2752
2895
  */
2753
- _CollectionCache.prototype.reset = function (aKeptElementPredicates) {
2754
- var mChangeListeners = this.mChangeListeners,
2755
- mByPredicate = this.aElements.$byPredicate,
2896
+ _CollectionCache.prototype.reset = function (aKeptElementPredicates, bKeepCreated) {
2897
+ var mByPredicate = this.aElements.$byPredicate,
2898
+ mChangeListeners = this.mChangeListeners,
2899
+ iCreated = 0, // index (and finally number) of created elements that we keep
2900
+ oElement,
2901
+ i,
2756
2902
  that = this;
2757
2903
 
2904
+ if (bKeepCreated) {
2905
+ this.oBackup = {};
2906
+ this.oBackup.iActiveElements = this.iActiveElements;
2907
+ this.oBackup.mChangeListeners = this.mChangeListeners;
2908
+ this.oBackup.sContext = this.sContext;
2909
+ this.oBackup.aElements = this.aElements.slice();
2910
+ this.oBackup.$byPredicate = mByPredicate;
2911
+ this.oBackup.$count = this.aElements.$count;
2912
+ this.oBackup.$created = this.aElements.$created;
2913
+ this.oBackup.iLimit = this.iLimit;
2914
+ }
2915
+
2916
+ for (i = 0; i < this.aElements.$created; i += 1) {
2917
+ oElement = this.aElements[i];
2918
+ if (_Helper.getPrivateAnnotation(oElement, "transient")
2919
+ || bKeepCreated && "@$ui5.context.isInactive" in oElement) {
2920
+ aKeptElementPredicates.push(_Helper.getPrivateAnnotation(oElement, "predicate")
2921
+ || _Helper.getPrivateAnnotation(oElement, "transientPredicate"));
2922
+ this.aElements[iCreated] = oElement;
2923
+ iCreated += 1;
2924
+ } else { // Note: "created persisted" elements must be active
2925
+ this.iActiveElements -= 1;
2926
+ }
2927
+ }
2758
2928
  this.mChangeListeners = {};
2759
2929
  this.sContext = undefined;
2760
- this.aElements = [];
2930
+ this.aElements.length = this.aElements.$created = iCreated;
2761
2931
  this.aElements.$byPredicate = {};
2762
2932
  this.aElements.$count = undefined; // needed for setCount()
2763
- this.aElements.$created = 0;
2764
2933
  this.iLimit = Infinity;
2765
2934
 
2766
2935
  Object.keys(mChangeListeners).forEach(function (sPath) {
@@ -2773,6 +2942,32 @@ sap.ui.define([
2773
2942
  });
2774
2943
  };
2775
2944
 
2945
+ /**
2946
+ * Restores the last backup taken by {@link #reset} with <code>bKeepCreated</code>, if told to
2947
+ * really do so; drops the backup in any case to free memory.
2948
+ *
2949
+ * @param {boolean} bReally - Whether to really restore, not just drop the backup
2950
+ *
2951
+ * @public
2952
+ */
2953
+ _CollectionCache.prototype.restore = function (bReally) {
2954
+ if (bReally) {
2955
+ this.iActiveElements = this.oBackup.iActiveElements;
2956
+ this.mChangeListeners = this.oBackup.mChangeListeners;
2957
+ this.sContext = this.oBackup.sContext;
2958
+ // Note: do not change reference to this.aElements! It's kept in closures :-(
2959
+ this.aElements.length = this.oBackup.aElements.length;
2960
+ this.oBackup.aElements.forEach(function (oElement, i) {
2961
+ this[i] = oElement;
2962
+ }, this.aElements);
2963
+ this.aElements.$byPredicate = this.oBackup.$byPredicate;
2964
+ this.aElements.$count = this.oBackup.$count;
2965
+ this.aElements.$created = this.oBackup.$created;
2966
+ this.iLimit = this.oBackup.iLimit;
2967
+ }
2968
+ this.oBackup = null;
2969
+ };
2970
+
2776
2971
  //*********************************************************************************************
2777
2972
  // PropertyCache
2778
2973
  //*********************************************************************************************
@@ -3134,7 +3329,6 @@ sap.ui.define([
3134
3329
  _SingleCache.prototype.requestSideEffects = function (oGroupLock, aPaths,
3135
3330
  mNavigationPropertyPaths, sResourcePath) {
3136
3331
  var mMergeableQueryOptions,
3137
- oOldValuePromise = this.oPromise,
3138
3332
  mQueryOptions,
3139
3333
  oResult,
3140
3334
  bSkip,
@@ -3142,7 +3336,7 @@ sap.ui.define([
3142
3336
 
3143
3337
  this.checkSharedRequest();
3144
3338
 
3145
- mQueryOptions = oOldValuePromise && _Helper.intersectQueryOptions(
3339
+ mQueryOptions = this.oPromise && _Helper.intersectQueryOptions(
3146
3340
  Object.assign({}, this.mQueryOptions, this.mLateQueryOptions), aPaths,
3147
3341
  this.oRequestor.getModelInterface().fetchMetadata,
3148
3342
  this.sMetaPath, mNavigationPropertyPaths);
@@ -3156,7 +3350,7 @@ sap.ui.define([
3156
3350
  oResult = SyncPromise.all([
3157
3351
  this.oRequestor.request("GET", sResourcePath, oGroupLock, undefined, undefined,
3158
3352
  undefined, undefined, this.sMetaPath, undefined, false, mMergeableQueryOptions,
3159
- function (aOtherPaths) {
3353
+ this, function (aOtherPaths) {
3160
3354
  if (arguments.length) {
3161
3355
  aPaths = aPaths.concat(aOtherPaths);
3162
3356
  } else {
@@ -3395,6 +3589,7 @@ sap.ui.define([
3395
3589
  _Cache.makeUpdateData = function (aPropertyPath, vValue) {
3396
3590
  return aPropertyPath.reduceRight(function (vValue0, sSegment) {
3397
3591
  var oResult = {};
3592
+
3398
3593
  oResult[sSegment] = vValue0;
3399
3594
  return oResult;
3400
3595
  }, vValue);