@openui5/sap.ui.core 1.104.0 → 1.105.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 (291) hide show
  1. package/.reuse/dep5 +1 -1
  2. package/THIRDPARTY.txt +1 -1
  3. package/package.json +1 -1
  4. package/src/jquery.sap.global.js +1 -1
  5. package/src/jquery.sap.properties.js +1 -1
  6. package/src/jquery.sap.resources.js +1 -1
  7. package/src/jquery.sap.script.js +1 -1
  8. package/src/jquery.sap.storage.js +3 -3
  9. package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
  10. package/src/sap/base/util/restricted/_castArray.js +1 -1
  11. package/src/sap/base/util/restricted/_compact.js +1 -1
  12. package/src/sap/base/util/restricted/_curry.js +1 -1
  13. package/src/sap/base/util/restricted/_debounce.js +1 -1
  14. package/src/sap/base/util/restricted/_difference.js +1 -1
  15. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  16. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  17. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  18. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  19. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  20. package/src/sap/base/util/restricted/_flatten.js +1 -1
  21. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  22. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  23. package/src/sap/base/util/restricted/_intersection.js +1 -1
  24. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  25. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  26. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  27. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  28. package/src/sap/base/util/restricted/_isNil.js +1 -1
  29. package/src/sap/base/util/restricted/_max.js +1 -1
  30. package/src/sap/base/util/restricted/_merge.js +1 -1
  31. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  32. package/src/sap/base/util/restricted/_min.js +1 -1
  33. package/src/sap/base/util/restricted/_omit.js +1 -1
  34. package/src/sap/base/util/restricted/_pick.js +1 -1
  35. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  36. package/src/sap/base/util/restricted/_throttle.js +1 -1
  37. package/src/sap/base/util/restricted/_toArray.js +1 -1
  38. package/src/sap/base/util/restricted/_union.js +1 -1
  39. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  40. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  41. package/src/sap/base/util/restricted/_uniq.js +1 -1
  42. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  43. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  44. package/src/sap/base/util/restricted/_without.js +1 -1
  45. package/src/sap/base/util/restricted/_xor.js +1 -1
  46. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  47. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  48. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  49. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  50. package/src/sap/ui/Device.js +5 -5
  51. package/src/sap/ui/Global.js +4 -4
  52. package/src/sap/ui/base/Event.js +1 -1
  53. package/src/sap/ui/base/EventProvider.js +1 -1
  54. package/src/sap/ui/base/Interface.js +1 -1
  55. package/src/sap/ui/base/ManagedObject.js +1 -1
  56. package/src/sap/ui/base/ManagedObjectMetadata.js +1 -1
  57. package/src/sap/ui/base/ManagedObjectObserver.js +2 -2
  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/core/.library +54 -51
  62. package/src/sap/ui/core/AccessKeysEnablement.js +173 -0
  63. package/src/sap/ui/core/BusyIndicator.js +1 -1
  64. package/src/sap/ui/core/Component.js +1 -1
  65. package/src/sap/ui/core/ComponentContainer.js +1 -1
  66. package/src/sap/ui/core/ComponentMetadata.js +11 -11
  67. package/src/sap/ui/core/ComponentSupport.js +1 -1
  68. package/src/sap/ui/core/Configuration.js +33 -5
  69. package/src/sap/ui/core/Control.js +1 -1
  70. package/src/sap/ui/core/Core.js +1 -1
  71. package/src/sap/ui/core/CustomData.js +1 -1
  72. package/src/sap/ui/core/DeclarativeSupport.js +1 -1
  73. package/src/sap/ui/core/Element.js +1 -1
  74. package/src/sap/ui/core/ElementMetadata.js +6 -4
  75. package/src/sap/ui/core/EnabledPropagator.js +1 -1
  76. package/src/sap/ui/core/EventBus.js +1 -1
  77. package/src/sap/ui/core/ExtensionPoint.js +2 -2
  78. package/src/sap/ui/core/Fragment.js +1 -1
  79. package/src/sap/ui/core/HTML.js +1 -1
  80. package/src/sap/ui/core/History.js +1 -1
  81. package/src/sap/ui/core/Icon.js +1 -1
  82. package/src/sap/ui/core/IndicationColorSupport.js +1 -1
  83. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  84. package/src/sap/ui/core/InvisibleMessage.js +1 -1
  85. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  86. package/src/sap/ui/core/InvisibleText.js +1 -1
  87. package/src/sap/ui/core/Item.js +1 -1
  88. package/src/sap/ui/core/LabelEnablement.js +1 -1
  89. package/src/sap/ui/core/LayoutData.js +1 -1
  90. package/src/sap/ui/core/ListItem.js +1 -1
  91. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  92. package/src/sap/ui/core/Locale.js +1 -1
  93. package/src/sap/ui/core/LocaleData.js +2 -3
  94. package/src/sap/ui/core/Manifest.js +3 -5
  95. package/src/sap/ui/core/Message.js +1 -1
  96. package/src/sap/ui/core/RenderManager.js +1 -1
  97. package/src/sap/ui/core/Renderer.js +1 -1
  98. package/src/sap/ui/core/ResizeHandler.js +1 -1
  99. package/src/sap/ui/core/ScrollBar.js +1 -1
  100. package/src/sap/ui/core/SeparatorItem.js +1 -1
  101. package/src/sap/ui/core/Title.js +1 -1
  102. package/src/sap/ui/core/TooltipBase.js +1 -1
  103. package/src/sap/ui/core/UIArea.js +1 -1
  104. package/src/sap/ui/core/UIComponent.js +1 -1
  105. package/src/sap/ui/core/UIComponentMetadata.js +1 -1
  106. package/src/sap/ui/core/ValueStateSupport.js +1 -1
  107. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  108. package/src/sap/ui/core/XMLComposite.js +4 -1
  109. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  110. package/src/sap/ui/core/_IconRegistry.js +1 -1
  111. package/src/sap/ui/core/date/Buddhist.js +4 -4
  112. package/src/sap/ui/core/date/UniversalDate.js +144 -34
  113. package/src/sap/ui/core/delegate/ItemNavigation.js +2 -2
  114. package/src/sap/ui/core/delegate/ScrollEnablement.js +1 -1
  115. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  116. package/src/sap/ui/core/dnd/DragDropInfo.js +3 -3
  117. package/src/sap/ui/core/dnd/DragInfo.js +1 -1
  118. package/src/sap/ui/core/dnd/DropInfo.js +1 -1
  119. package/src/sap/ui/core/format/DateFormat.js +31 -9
  120. package/src/sap/ui/core/format/TimezoneUtil.js +1 -1
  121. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  122. package/src/sap/ui/core/library.js +44 -3
  123. package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
  124. package/src/sap/ui/core/message/Message.js +1 -1
  125. package/src/sap/ui/core/message/MessageManager.js +1 -1
  126. package/src/sap/ui/core/message/MessageParser.js +1 -1
  127. package/src/sap/ui/core/message/MessageProcessor.js +1 -1
  128. package/src/sap/ui/core/messagebundle.properties +2 -0
  129. package/src/sap/ui/core/messagebundle_cy.properties +1 -1
  130. package/src/sap/ui/core/messagebundle_el.properties +1 -1
  131. package/src/sap/ui/core/messagebundle_en.properties +57 -56
  132. package/src/sap/ui/core/messagebundle_en_GB.properties +57 -56
  133. package/src/sap/ui/core/messagebundle_fr.properties +1 -1
  134. package/src/sap/ui/core/messagebundle_fr_CA.properties +1 -1
  135. package/src/sap/ui/core/messagebundle_hi.properties +1 -1
  136. package/src/sap/ui/core/messagebundle_hu.properties +1 -1
  137. package/src/sap/ui/core/messagebundle_ko.properties +4 -4
  138. package/src/sap/ui/core/messagebundle_sh.properties +1 -1
  139. package/src/sap/ui/core/messagebundle_vi.properties +1 -1
  140. package/src/sap/ui/core/mvc/Controller.js +12 -12
  141. package/src/sap/ui/core/mvc/HTMLView.js +1 -1
  142. package/src/sap/ui/core/mvc/JSONView.js +1 -1
  143. package/src/sap/ui/core/mvc/JSView.js +1 -1
  144. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  145. package/src/sap/ui/core/mvc/View.js +7 -7
  146. package/src/sap/ui/core/mvc/XMLView.js +1 -1
  147. package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
  148. package/src/sap/ui/core/plugin/LessSupport.js +1 -1
  149. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  150. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  151. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  152. package/src/sap/ui/core/routing/Router.js +3 -3
  153. package/src/sap/ui/core/search/OpenSearchProvider.js +2 -2
  154. package/src/sap/ui/core/search/SearchProvider.js +2 -2
  155. package/src/sap/ui/core/service/Service.js +1 -1
  156. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  157. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  158. package/src/sap/ui/core/support/Plugin.js +1 -1
  159. package/src/sap/ui/core/support/Support.js +2 -3
  160. package/src/sap/ui/core/support/plugins/ControlTree.js +1 -1
  161. package/src/sap/ui/core/support/plugins/Debugging.js +1 -1
  162. package/src/sap/ui/core/support/plugins/Interaction.js +1 -1
  163. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
  164. package/src/sap/ui/core/support/plugins/Performance.js +1 -1
  165. package/src/sap/ui/core/support/plugins/Selector.js +1 -1
  166. package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
  167. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  168. package/src/sap/ui/core/support/plugins/ViewInfo.js +2 -3
  169. package/src/sap/ui/core/themes/base/Icon.less +4 -0
  170. package/src/sap/ui/core/themes/base/global.less +5 -1
  171. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  172. package/src/sap/ui/core/tmpl/DOMElement.js +1 -1
  173. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  174. package/src/sap/ui/core/tmpl/Template.js +1 -1
  175. package/src/sap/ui/core/tmpl/TemplateControl.js +1 -1
  176. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  177. package/src/sap/ui/core/util/Export.js +1 -1
  178. package/src/sap/ui/core/util/ExportCell.js +1 -1
  179. package/src/sap/ui/core/util/ExportColumn.js +1 -1
  180. package/src/sap/ui/core/util/ExportRow.js +1 -1
  181. package/src/sap/ui/core/util/ExportType.js +1 -1
  182. package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
  183. package/src/sap/ui/core/util/File.js +1 -1
  184. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  185. package/src/sap/ui/core/util/MockServer.js +1 -1
  186. package/src/sap/ui/core/util/PasteHelper.js +1 -1
  187. package/src/sap/ui/core/util/reflection/BaseTreeModifier.js +0 -3
  188. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
  189. package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
  190. package/src/sap/ui/core/util/serializer/ViewSerializer.js +1 -1
  191. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
  192. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  193. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  194. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  195. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  196. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  197. package/src/sap/ui/core/ws/WebSocket.js +1 -1
  198. package/src/sap/ui/debug/ControlTree.js +1 -1
  199. package/src/sap/ui/debug/DebugEnv.js +1 -1
  200. package/src/sap/ui/debug/PropertyList.js +1 -1
  201. package/src/sap/ui/model/ClientModel.js +1 -1
  202. package/src/sap/ui/model/CompositeDataState.js +1 -1
  203. package/src/sap/ui/model/CompositeType.js +1 -1
  204. package/src/sap/ui/model/DataState.js +1 -1
  205. package/src/sap/ui/model/MetaModel.js +1 -1
  206. package/src/sap/ui/model/Model.js +1 -1
  207. package/src/sap/ui/model/SelectionModel.js +1 -1
  208. package/src/sap/ui/model/SimpleType.js +1 -1
  209. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  210. package/src/sap/ui/model/Type.js +1 -1
  211. package/src/sap/ui/model/_Helper.js +3 -1
  212. package/src/sap/ui/model/base/ManagedObjectModel.js +2 -2
  213. package/src/sap/ui/model/json/JSONModel.js +1 -1
  214. package/src/sap/ui/model/message/MessageModel.js +1 -1
  215. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  216. package/src/sap/ui/model/odata/ODataMessageParser.js +4 -4
  217. package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
  218. package/src/sap/ui/model/odata/ODataMetadata.js +1 -1
  219. package/src/sap/ui/model/odata/ODataModel.js +1 -1
  220. package/src/sap/ui/model/odata/ODataTreeBindingFlat.js +310 -153
  221. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  222. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  223. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  224. package/src/sap/ui/model/odata/type/Date.js +1 -1
  225. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  226. package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
  227. package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
  228. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -1
  229. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  230. package/src/sap/ui/model/odata/type/Double.js +1 -1
  231. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  232. package/src/sap/ui/model/odata/type/Int.js +1 -1
  233. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  234. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  235. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  236. package/src/sap/ui/model/odata/type/ODataType.js +1 -1
  237. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  238. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  239. package/src/sap/ui/model/odata/type/Single.js +1 -1
  240. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  241. package/src/sap/ui/model/odata/type/String.js +1 -1
  242. package/src/sap/ui/model/odata/type/Time.js +1 -1
  243. package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
  244. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  245. package/src/sap/ui/model/odata/v2/Context.js +1 -1
  246. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  247. package/src/sap/ui/model/odata/v2/ODataListBinding.js +25 -0
  248. package/src/sap/ui/model/odata/v2/ODataModel.js +50 -19
  249. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +4 -1
  250. package/src/sap/ui/model/odata/v4/Context.js +84 -30
  251. package/src/sap/ui/model/odata/v4/ODataBinding.js +4 -8
  252. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +26 -27
  253. package/src/sap/ui/model/odata/v4/ODataListBinding.js +120 -93
  254. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +1 -1
  255. package/src/sap/ui/model/odata/v4/ODataModel.js +3 -2
  256. package/src/sap/ui/model/odata/v4/ODataParentBinding.js +10 -13
  257. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +4 -4
  258. package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +135 -28
  259. package/src/sap/ui/model/odata/v4/lib/_AggregationHelper.js +133 -16
  260. package/src/sap/ui/model/odata/v4/lib/_Cache.js +267 -137
  261. package/src/sap/ui/model/odata/v4/lib/_Helper.js +31 -9
  262. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +5 -5
  263. package/src/sap/ui/model/resource/ResourceModel.js +1 -1
  264. package/src/sap/ui/model/type/Boolean.js +1 -1
  265. package/src/sap/ui/model/type/Currency.js +1 -1
  266. package/src/sap/ui/model/type/Date.js +1 -1
  267. package/src/sap/ui/model/type/DateInterval.js +1 -1
  268. package/src/sap/ui/model/type/DateTime.js +1 -1
  269. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  270. package/src/sap/ui/model/type/FileSize.js +1 -1
  271. package/src/sap/ui/model/type/Float.js +1 -1
  272. package/src/sap/ui/model/type/Integer.js +1 -1
  273. package/src/sap/ui/model/type/String.js +1 -1
  274. package/src/sap/ui/model/type/Time.js +1 -1
  275. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  276. package/src/sap/ui/model/type/Unit.js +1 -1
  277. package/src/sap/ui/model/xml/XMLModel.js +4 -2
  278. package/src/sap/ui/performance/trace/FESR.js +27 -24
  279. package/src/sap/ui/performance/trace/Interaction.js +66 -16
  280. package/src/sap/ui/qunit/utils/ControlIterator.js +1 -1
  281. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +1 -1
  282. package/src/sap/ui/test/actions/Press.js +7 -0
  283. package/src/sap/ui/test/generic/TestBase.js +1 -1
  284. package/src/sap/ui/test/matchers/AggregationContainsPropertyEqual.js +2 -3
  285. package/src/sap/ui/test/matchers/AggregationFilled.js +2 -3
  286. package/src/sap/ui/test/matchers/AggregationLengthEquals.js +2 -3
  287. package/src/sap/ui/test/opaQunit.js +11 -6
  288. package/src/sap/ui/test/pipelines/ActionPipeline.js +2 -3
  289. package/src/sap/ui/test/pipelines/MatcherPipeline.js +2 -3
  290. package/src/sap/ui/test/pipelines/PipelineFactory.js +2 -3
  291. package/src/sap/ui/util/Storage.js +1 -1
@@ -108,11 +108,11 @@ sap.ui.define([
108
108
  // creates the cache does not call #setActive)
109
109
  this.iActiveUsages = 1;
110
110
  this.mChangeListeners = {}; // map from path to an array of change listeners
111
+ this.mChangeRequests = {}; // map from path to an array of DELETE or PATCH promises
111
112
  this.fnGetOriginalResourcePath = fnGetOriginalResourcePath;
112
113
  // the point in time when the cache became inactive; active caches have Infinity so that
113
114
  // they are always "newer"
114
115
  this.iInactiveSince = Infinity;
115
- this.mPatchRequests = {}; // map from path to an array of (PATCH) promises
116
116
  this.mEditUrl2PatchPromise = {}; // map from edit URL to a PATCH promise for retry
117
117
  // a promise with attached properties $count, $resolve existing while DELETEs or POSTs are
118
118
  // being sent
@@ -147,11 +147,12 @@ sap.ui.define([
147
147
  * @param {boolean} [bDoNotRequestCount]
148
148
  * Whether not to request the new count from the server; useful in case of
149
149
  * {@link sap.ui.model.odata.v4.Context#replaceWith} where it is known that the count remains
150
- * unchanged; w/o a lock this should be true
151
- * @param {function} fnCallback
152
- * A function which is called after a transient entity has been deleted from the cache or
153
- * after the entity has been deleted from the server and from the cache; the index of the
154
- * entity and the entity list are both passed as parameter, or none of them
150
+ * unchanged; only used when deleting from an entity collection
151
+ * @param {function} [fnCallback]
152
+ * A function which is called immediately when an entity has been deleted from the cache, or
153
+ * when it was re-inserted due to an error; only used when deleting from an entity collection,
154
+ * the index of the entity and an offset (-1 for deletion, 1 for re-insertion) are passed as
155
+ * parameter
155
156
  * @returns {sap.ui.base.SyncPromise}
156
157
  * A promise which is resolved without a result in case of success, or rejected with an
157
158
  * instance of <code>Error</code> in case of failure
@@ -163,23 +164,25 @@ sap.ui.define([
163
164
  bDoNotRequestCount, fnCallback) {
164
165
  var aSegments = sPath.split("/"),
165
166
  vDeleteProperty = aSegments.pop(),
166
- iIndex = rNumber.test(vDeleteProperty) ? Number(vDeleteProperty) : undefined,
167
167
  sParentPath = aSegments.join("/"),
168
168
  that = this;
169
169
 
170
170
  this.checkSharedRequest();
171
- this.addPendingRequest();
172
171
 
173
172
  return this.fetchValue(_GroupLock.$cached, sParentPath).then(function (vCacheData) {
174
173
  var vCachePath = _Cache.from$skip(vDeleteProperty, vCacheData),
174
+ oDeleted,
175
175
  oEntity = vDeleteProperty
176
176
  ? vCacheData[vCachePath] || vCacheData.$byPredicate[vCachePath]
177
177
  : vCacheData, // deleting at root level
178
178
  mHeaders,
179
+ iIndex = typeof vCachePath === "number" ? vCachePath : undefined,
179
180
  sKeyPredicate = _Helper.getPrivateAnnotation(oEntity, "predicate"),
180
181
  sEntityPath = _Helper.buildPath(sParentPath,
181
182
  Array.isArray(vCacheData) ? sKeyPredicate : vDeleteProperty),
182
- sTransientGroup = _Helper.getPrivateAnnotation(oEntity, "transient");
183
+ oRequestPromise,
184
+ sTransientGroup = _Helper.getPrivateAnnotation(oEntity, "transient"),
185
+ sTransientPredicate = _Helper.getPrivateAnnotation(oEntity, "transientPredicate");
183
186
 
184
187
  if (sTransientGroup) {
185
188
  if (typeof sTransientGroup !== "string") {
@@ -188,50 +191,108 @@ sap.ui.define([
188
191
  that.oRequestor.removePost(sTransientGroup, oEntity);
189
192
  return undefined;
190
193
  }
191
- if (oEntity["$ui5.deleting"]) {
194
+ if (oEntity["@$ui5.context.isDeleted"]) {
192
195
  throw new Error("Must not delete twice: " + sEditUrl);
193
196
  }
194
- oEntity["$ui5.deleting"] = true;
197
+ oEntity["@$ui5.context.isDeleted"] = true;
198
+ if (Array.isArray(vCacheData)) {
199
+ oDeleted = that.addDeleted(vCacheData, iIndex, sKeyPredicate, oGroupLock,
200
+ !!sTransientPredicate);
201
+ that.removeElement(vCacheData, iIndex, sKeyPredicate, sParentPath);
202
+ fnCallback(iIndex, -1);
203
+ }
195
204
  mHeaders = {"If-Match" : oETagEntity || oEntity};
196
205
  sEditUrl += that.oRequestor.buildQueryString(that.sMetaPath, that.mQueryOptions, true);
206
+ // the existence of an onCancel callback causes a pending change in the requestor
207
+ oRequestPromise = oGroupLock
208
+ ? that.oRequestor.request("DELETE", sEditUrl, oGroupLock.getUnlockedCopy(),
209
+ mHeaders, undefined, undefined, /*onCancel*/function () {}, undefined,
210
+ _Helper.buildPath(that.getOriginalResourcePath(oEntity), sEntityPath))
211
+ : SyncPromise.resolve();
212
+ _Helper.addByPath(that.mChangeRequests, sEntityPath, oRequestPromise);
197
213
  return SyncPromise.all([
198
- oGroupLock
199
- && that.oRequestor.request("DELETE", sEditUrl, oGroupLock.getUnlockedCopy(),
200
- mHeaders, undefined, undefined, undefined, undefined,
201
- _Helper.buildPath(that.getOriginalResourcePath(oEntity), sEntityPath))
202
- .catch(function (oError) {
203
- if (oError.status !== 404) {
204
- delete oEntity["$ui5.deleting"];
205
- throw oError;
206
- } // else: map 404 to 200
207
- }),
214
+ oRequestPromise.catch(function (oError) {
215
+ if (oError.status !== 404) {
216
+ throw oError;
217
+ } // else: map 404 to 200
218
+ }),
208
219
  iIndex === undefined // single element or kept-alive not in list
209
220
  && !bDoNotRequestCount
210
221
  && that.requestCount(oGroupLock || that.oRequestor.lockGroup("$auto", that)),
211
222
  oGroupLock && oGroupLock.unlock() // unlock when all requests have been queued
212
223
  ]).then(function () {
213
224
  if (Array.isArray(vCacheData)) {
214
- fnCallback(
215
- that.removeElement(vCacheData, iIndex, sKeyPredicate, sParentPath),
216
- vCacheData);
217
- } else {
218
- if (vDeleteProperty) {
219
- // set to null and notify listeners
220
- _Helper.updateExisting(that.mChangeListeners, sParentPath,
221
- vCacheData, _Cache.makeUpdateData([vDeleteProperty], null));
222
- } else { // deleting at root level
223
- oEntity["$ui5.deleted"] = true;
224
- }
225
- fnCallback();
225
+ vCacheData.$deleted.splice(vCacheData.$deleted.indexOf(oDeleted), 1);
226
+ delete vCacheData.$byPredicate[sKeyPredicate];
227
+ delete vCacheData.$byPredicate[sTransientPredicate];
228
+ } else if (vDeleteProperty) {
229
+ // set to null and notify listeners
230
+ _Helper.updateExisting(that.mChangeListeners, sParentPath,
231
+ vCacheData, _Cache.makeUpdateData([vDeleteProperty], null));
232
+ } else { // deleting at root level
233
+ oEntity["$ui5.deleted"] = true;
226
234
  }
227
235
  that.oRequestor.getModelInterface().reportStateMessages(that.sResourcePath,
228
236
  {}, [sEntityPath]);
237
+ }, function (oError) {
238
+ var iDeletedIndex;
239
+
240
+ delete oEntity["@$ui5.context.isDeleted"];
241
+ if (Array.isArray(vCacheData)) {
242
+ addToCount(that.mChangeListeners, sParentPath, vCacheData, 1);
243
+ iIndex = oDeleted.index;
244
+ iDeletedIndex = vCacheData.$deleted.indexOf(oDeleted);
245
+ that.adjustIndexes(sParentPath, vCacheData, iIndex, 1, iDeletedIndex);
246
+ vCacheData.splice(iIndex, 0, oEntity);
247
+ vCacheData.$deleted.splice(iDeletedIndex, 1);
248
+ if (sTransientPredicate) {
249
+ vCacheData.$created += 1;
250
+ if (!sParentPath) {
251
+ that.iActiveElements += 1;
252
+ }
253
+ }
254
+ fnCallback(iIndex, 1);
255
+ }
256
+ throw oError;
257
+ }).finally(function () {
258
+ _Helper.removeByPath(that.mChangeRequests, sEntityPath, oRequestPromise);
229
259
  });
230
- }).finally(function () {
231
- that.removePendingRequest();
232
260
  });
233
261
  };
234
262
 
263
+ /**
264
+ * Adds an entry about a deleted entity to <code>aElements.$deleted</code>. Ensures that the
265
+ * entries are ordered by entity index and deletion order (if two entities were deleted on the
266
+ * same index, the second one must be behind).
267
+ *
268
+ * @param {object[]} aElements - The elements collection
269
+ * @param {number} iIndex - The entity's index
270
+ * @param {string} sPredicate - The entity's key predicate
271
+ * @param {sap.ui.model.odata.v4.lib._GroupLock|undefined} oGroupLock - The deletion group lock
272
+ * @param {boolean} bCreated - Whether the entity was created
273
+ * @returns {object} The deletion info
274
+ *
275
+ * @private
276
+ */
277
+ _Cache.prototype.addDeleted = function (aElements, iIndex, sPredicate, oGroupLock, bCreated) {
278
+ var oDeleted = {
279
+ created : bCreated,
280
+ groupId : oGroupLock && oGroupLock.getGroupId(),
281
+ predicate : sPredicate,
282
+ index : iIndex
283
+ },
284
+ i;
285
+
286
+ aElements.$deleted = aElements.$deleted || [];
287
+ for (i = 0; i < aElements.$deleted.length; i += 1) {
288
+ if (iIndex < aElements.$deleted[i].index) {
289
+ break;
290
+ }
291
+ }
292
+ aElements.$deleted.splice(i, 0, oDeleted);
293
+ return oDeleted;
294
+ };
295
+
235
296
  /**
236
297
  * Adds one to the count of pending (that is, "currently being sent to the server") requests.
237
298
  *
@@ -250,6 +311,39 @@ sap.ui.define([
250
311
  this.oPendingRequestsPromise.$count += 1;
251
312
  };
252
313
 
314
+ /**
315
+ * Adjusts the indexes in the collection.
316
+ *
317
+ * @param {string} sPath The path of the collection in the cache
318
+ * @param {object[]} aElements The collection
319
+ * @param {number} iIndex The index at which the element has been inserted or removed
320
+ * @param {number} iOffset The offset (1 = insert, -1 = remove)
321
+ * @param {number} iDeletedIndex The element's index in $deleted (only for re-insertion)
322
+ * @param {boolean} bCreate Whether the insert is a create (and not reverting a delete)
323
+ *
324
+ * @private
325
+ */
326
+ _Cache.prototype.adjustIndexes = function (sPath, aElements, iIndex, iOffset, iDeletedIndex,
327
+ bCreate) {
328
+ if (!sPath) {
329
+ // If the path is empty, we are in a _CollectionCache and aReadRequest exists
330
+ this.aReadRequests.forEach(function (oReadRequest) {
331
+ if (oReadRequest.iStart >= iIndex) {
332
+ oReadRequest.iStart += iOffset;
333
+ oReadRequest.iEnd += iOffset;
334
+ } // Note: no changes can happen inside *gaps*
335
+ });
336
+ }
337
+ (aElements.$deleted || []).forEach(function (oDeleted, i) {
338
+ if (iIndex < oDeleted.index || iDeletedIndex < i // before the deleted one
339
+ || bCreate
340
+ && (iIndex === 0 // create at start
341
+ || !oDeleted.created)) { // the deleted one was not created
342
+ oDeleted.index += iOffset;
343
+ }
344
+ });
345
+ };
346
+
253
347
  /**
254
348
  * Calculates and returns the key predicate for the given entity and stores it as private
255
349
  * annotation at the given entity. If at least one key property is <code>undefined</code>, no
@@ -335,19 +429,17 @@ sap.ui.define([
335
429
 
336
430
  // Clean-up when the create has been canceled.
337
431
  function cleanUp() {
432
+ var iIndex = aCollection.indexOf(oEntityData);
433
+
338
434
  _Helper.removeByPath(that.mPostRequests, sPath, oEntityData);
339
- aCollection.splice(aCollection.indexOf(oEntityData), 1);
435
+ aCollection.splice(iIndex, 1);
340
436
  aCollection.$created -= 1;
341
437
  if (!oEntityData["@$ui5.context.isInactive"]) {
342
438
  that.iActiveElements -= 1;
343
439
  addToCount(that.mChangeListeners, sPath, aCollection, -1);
344
440
  }
345
441
  delete aCollection.$byPredicate[sTransientPredicate];
346
- if (!sPath) {
347
- // Note: sPath is empty only in a CollectionCache, so we may call adjustReadRequests
348
- // Note: index 0 is OK here (see "Must not request created element")
349
- that.adjustReadRequests(0, -1);
350
- }
442
+ that.adjustIndexes(sPath, aCollection, iIndex, -1);
351
443
  oGroupLock.cancel();
352
444
  }
353
445
 
@@ -457,10 +549,7 @@ sap.ui.define([
457
549
  // if the nested collection is empty $byPredicate is not available, create it on demand
458
550
  aCollection.$byPredicate = aCollection.$byPredicate || {};
459
551
  aCollection.$byPredicate[sTransientPredicate] = oEntityData;
460
- if (!sPath) {
461
- // Note: sPath is empty only in a CollectionCache, so we may call adjustReadRequests
462
- that.adjustReadRequests(0, 1);
463
- }
552
+ that.adjustIndexes(sPath, aCollection, 0, 1, 0, true);
464
553
 
465
554
  return oPostPathPromise.then(function (sPostPath) {
466
555
  sPostPath += that.oRequestor.buildQueryString(that.sMetaPath, that.mQueryOptions, true);
@@ -478,7 +567,7 @@ sap.ui.define([
478
567
  *
479
568
  * @public
480
569
  */
481
- _Cache.prototype.deregisterChange = function (sPath, oListener) {
570
+ _Cache.prototype.deregisterChangeListener = function (sPath, oListener) {
482
571
  if (!this.bSharedRequest) {
483
572
  _Helper.removeByPath(this.mChangeListeners, sPath, oListener);
484
573
  }
@@ -526,11 +615,12 @@ sap.ui.define([
526
615
  * @param {object} oValue - The object that is expected to have the value
527
616
  * @param {string} sSegment - The path segment that is missing
528
617
  * @param {number} iPathLength - The length of the path of the missing value
618
+ * @param {boolean} [bAgain] - Whether we are trying again and must not cause a request
529
619
  * @returns {sap.ui.base.SyncPromise|undefined}
530
620
  * Returns a SyncPromise which resolves with the value or returns undefined in some
531
621
  * special cases.
532
622
  */
533
- function missingValue(oValue, sSegment, iPathLength) {
623
+ function missingValue(oValue, sSegment, iPathLength, bAgain) {
534
624
  var sPropertyName,
535
625
  sPropertyPath = aSegments.slice(0, iPathLength).join("/"),
536
626
  sPropertyMetaPath = _Helper.getMetaPath(sPropertyPath),
@@ -589,10 +679,10 @@ sap.ui.define([
589
679
  oEntity = oData;
590
680
  iEntityPathLength = 0;
591
681
  }
592
- return oEntity
682
+ return oEntity && !bAgain
593
683
  && that.fetchLateProperty(oGroupLock, oEntity,
594
684
  aSegments.slice(0, iEntityPathLength).join("/"),
595
- aSegments.slice(iEntityPathLength).join("/").split("@")[0],
685
+ aSegments.slice(iEntityPathLength).join("/"),
596
686
  aSegments.slice(iEntityPathLength, iPathLength).join("/"))
597
687
  || invalidSegment(sSegment);
598
688
  }
@@ -618,7 +708,7 @@ sap.ui.define([
618
708
  }
619
709
  aSegments = sPath.split("/");
620
710
  return aSegments.reduce(function (oPromise, sSegment, i) {
621
- return oPromise.then(function (vValue) {
711
+ return oPromise.then(function step(vValue, bAgain) {
622
712
  var vIndex, aMatches, oParentValue;
623
713
 
624
714
  if (sSegment === "$count") {
@@ -660,13 +750,17 @@ sap.ui.define([
660
750
  vValue = vValue[vIndex];
661
751
  }
662
752
  // missing advertisement or annotation is not an error
663
- vValue = vValue === undefined && sSegment[0] !== "#" && sSegment[0] !== "@"
664
- ? missingValue(oParentValue, sSegment, i + 1)
665
- : vValue;
753
+ if (vValue === undefined && sSegment[0] !== "#" && sSegment[0] !== "@") {
754
+ vValue = missingValue(oParentValue, sSegment, i + 1, bAgain);
755
+ if (vValue instanceof SyncPromise && vValue.isPending()) {
756
+ return vValue.then(function () { // repeat step once late property fetched
757
+ return step(oParentValue, true);
758
+ });
759
+ }
760
+ }
666
761
  if (sSegment.includes("@")) {
667
762
  bInAnnotation = true;
668
763
  }
669
-
670
764
  return vValue;
671
765
  });
672
766
  }, oDataPromise);
@@ -688,7 +782,8 @@ sap.ui.define([
688
782
  * The path of oResource relative to the cache
689
783
  * @param {string} sRequestedPropertyPath
690
784
  * The path of the requested property relative to oResource; this property is requested from
691
- * the server
785
+ * the server. For annotations, except client annotations, the annotated property is requested
786
+ * from the server.
692
787
  * @param {string} sMissingPropertyPath
693
788
  * The path of the missing property relative to oResource; this property is returned so that
694
789
  * drillDown can proceed
@@ -704,13 +799,14 @@ sap.ui.define([
704
799
  var sFullResourceMetaPath,
705
800
  sFullResourcePath,
706
801
  sGroupId,
802
+ iIndexOfAt = sRequestedPropertyPath.indexOf("@"),
707
803
  sMergeBasePath, // full resource path plus custom query options
708
804
  oPromise,
709
805
  mQueryOptions,
710
806
  sRequestPath,
711
807
  sResourceMetaPath = _Helper.getMetaPath(sResourcePath),
712
808
  mTypeForMetaPath = this.fetchTypes().getResult(),
713
- aUpdateProperties = [sRequestedPropertyPath],
809
+ aUpdateProperties,
714
810
  that = this;
715
811
 
716
812
  /*
@@ -732,9 +828,9 @@ sap.ui.define([
732
828
  oEntityType = that.oRequestor.fetchType(mTypeForMetaPath, sMetaPath).getResult();
733
829
  }
734
830
  if (sBasePath) {
735
- // Key properties and predicate must only be copied from the result for nested
736
- // properties. The root property is already loaded and has them already. We check
737
- // that they are unchanged in this case.
831
+ // The key properties must only be copied from the result for nested entities. The
832
+ // root entity is already loaded and has them already. We check that they are
833
+ // unchanged in this case.
738
834
  (oEntityType.$Key || []).forEach(function (vKey) {
739
835
  if (typeof vKey === "object") {
740
836
  vKey = vKey[Object.keys(vKey)[0]]; // the path for the alias
@@ -752,8 +848,16 @@ sap.ui.define([
752
848
  }
753
849
 
754
850
  if (!this.mLateQueryOptions) {
755
- return undefined;
851
+ return undefined; // no autoExpandSelect
852
+ }
853
+
854
+ if (iIndexOfAt >= 0) {
855
+ if (sRequestedPropertyPath.startsWith("@$ui5.", iIndexOfAt)) {
856
+ return undefined; // do not request for a client annotation
857
+ }
858
+ sRequestedPropertyPath = sRequestedPropertyPath.slice(0, iIndexOfAt);
756
859
  }
860
+ aUpdateProperties = [sRequestedPropertyPath];
757
861
 
758
862
  sFullResourceMetaPath = _Helper.buildPath(this.sMetaPath, sResourceMetaPath);
759
863
  // sRequestedPropertyPath is also a metapath because the binding does not accept a path with
@@ -761,7 +865,7 @@ sap.ui.define([
761
865
  mQueryOptions = _Helper.intersectQueryOptions(
762
866
  _Helper.getQueryOptionsForPath(this.mLateQueryOptions, sResourcePath),
763
867
  [sRequestedPropertyPath], this.oRequestor.getModelInterface().fetchMetadata,
764
- sFullResourceMetaPath, {});
868
+ sFullResourceMetaPath);
765
869
  if (!mQueryOptions) {
766
870
  return undefined;
767
871
  }
@@ -899,8 +1003,10 @@ sap.ui.define([
899
1003
  * @param {string} [sPath]
900
1004
  * Relative path to drill-down into, may be empty (only for collection cache)
901
1005
  * @returns {object[]} The cache elements
1006
+ *
1007
+ * @public
902
1008
  */
903
- _Cache.prototype.getAllElements = function (sPath) {
1009
+ _Cache.prototype.getAllElements = function (sPath) {
904
1010
  var aAllElements;
905
1011
 
906
1012
  if (sPath) {
@@ -1044,8 +1150,8 @@ sap.ui.define([
1044
1150
  * Whether there are any registered change listeners
1045
1151
  *
1046
1152
  * @public
1047
- * @see #deregisterChange
1048
- * @see #registerChange
1153
+ * @see #deregisterChangeListener
1154
+ * @see #registerChangeListener
1049
1155
  */
1050
1156
  _Cache.prototype.hasChangeListeners = function () {
1051
1157
  return !isEmptyObject(this.mChangeListeners);
@@ -1072,16 +1178,16 @@ sap.ui.define([
1072
1178
  bIgnoreTransient) {
1073
1179
  var that = this;
1074
1180
 
1075
- return Object.keys(this.mPatchRequests).some(function (sRequestPath) {
1076
- return isSubPath(sRequestPath, sPath)
1181
+ return Object.keys(this.mChangeRequests).some(function (sRequestPath) {
1182
+ return _Helper.hasPathPrefix(sRequestPath, sPath)
1077
1183
  && !(bIgnoreKeptAlive
1078
- && that.mPatchRequests[sRequestPath].every(function (oPatchPromise) {
1184
+ && that.mChangeRequests[sRequestPath].every(function (oPatchPromise) {
1079
1185
  return oPatchPromise.$isKeepAlive();
1080
1186
  }));
1081
1187
  }) || Object.keys(this.mPostRequests).some(function (sRequestPath) {
1082
1188
  return bIgnoreTransient && !sRequestPath
1083
1189
  ? false // ignore transient elements on top level
1084
- : isSubPath(sRequestPath, sPath)
1190
+ : _Helper.hasPathPrefix(sRequestPath, sPath)
1085
1191
  && that.mPostRequests[sRequestPath].some(function (oEntityData) {
1086
1192
  return !oEntityData["@$ui5.context.isInactive"];
1087
1193
  });
@@ -1331,7 +1437,7 @@ sap.ui.define([
1331
1437
  *
1332
1438
  * @private
1333
1439
  */
1334
- _Cache.prototype.registerChange = function (sPath, oListener) {
1440
+ _Cache.prototype.registerChangeListener = function (sPath, oListener) {
1335
1441
  if (!this.bSharedRequest) {
1336
1442
  _Helper.addByPath(this.mChangeListeners, sPath, oListener);
1337
1443
  }
@@ -1358,32 +1464,33 @@ sap.ui.define([
1358
1464
  * @private
1359
1465
  */
1360
1466
  _Cache.prototype.removeElement = function (aElements, iIndex, sPredicate, sPath) {
1361
- var oElement,
1362
- sTransientPredicate;
1467
+ var oElement = aElements.$byPredicate[sPredicate],
1468
+ bDeleted = oElement["@$ui5.context.isDeleted"],
1469
+ sTransientPredicate = _Helper.getPrivateAnnotation(oElement, "transientPredicate");
1363
1470
 
1364
- oElement = aElements.$byPredicate[sPredicate];
1365
1471
  if (iIndex !== undefined) {
1366
1472
  // the element might have moved due to parallel insert/delete
1367
1473
  iIndex = _Cache.getElementIndex(aElements, sPredicate, iIndex);
1368
1474
  aElements.splice(iIndex, 1);
1369
1475
  addToCount(this.mChangeListeners, sPath, aElements, -1);
1370
1476
  }
1371
- delete aElements.$byPredicate[sPredicate];
1372
- sTransientPredicate = _Helper.getPrivateAnnotation(oElement, "transientPredicate");
1477
+ if (!bDeleted) {
1478
+ delete aElements.$byPredicate[sPredicate];
1479
+ }
1373
1480
  if (sTransientPredicate) {
1374
1481
  aElements.$created -= 1;
1375
1482
  if (!sPath) {
1376
1483
  this.iActiveElements -= 1;
1377
1484
  }
1378
- delete aElements.$byPredicate[sTransientPredicate];
1485
+ if (!bDeleted) {
1486
+ delete aElements.$byPredicate[sTransientPredicate];
1487
+ }
1379
1488
  }
1380
- if (!sPath && iIndex !== undefined) {
1381
- // Note: sPath is empty only in a CollectionCache, so we may use iLimit and
1382
- // adjustReadRequests
1383
- if (!sTransientPredicate) {
1489
+ if (iIndex !== undefined) {
1490
+ this.adjustIndexes(sPath, aElements, iIndex, -1);
1491
+ if (!sPath && !sTransientPredicate) {
1384
1492
  this.iLimit -= 1; // this doesn't change Infinity
1385
1493
  }
1386
- this.adjustReadRequests(iIndex, -1);
1387
1494
  }
1388
1495
  return iIndex;
1389
1496
  };
@@ -1524,15 +1631,15 @@ sap.ui.define([
1524
1631
  _Cache.prototype.resetChangesForPath = function (sPath) {
1525
1632
  var that = this;
1526
1633
 
1527
- Object.keys(this.mPatchRequests).forEach(function (sRequestPath) {
1634
+ Object.keys(this.mChangeRequests).reverse().forEach(function (sRequestPath) {
1528
1635
  var aPromises, i;
1529
1636
 
1530
- if (isSubPath(sRequestPath, sPath)) {
1531
- aPromises = that.mPatchRequests[sRequestPath];
1637
+ if (_Helper.hasPathPrefix(sRequestPath, sPath)) {
1638
+ aPromises = that.mChangeRequests[sRequestPath];
1532
1639
  for (i = aPromises.length - 1; i >= 0; i -= 1) {
1533
- that.oRequestor.removePatch(aPromises[i]);
1640
+ that.oRequestor.removeChangeRequest(aPromises[i]);
1534
1641
  }
1535
- delete that.mPatchRequests[sRequestPath];
1642
+ delete that.mChangeRequests[sRequestPath];
1536
1643
  }
1537
1644
  });
1538
1645
 
@@ -1762,7 +1869,7 @@ sap.ui.define([
1762
1869
  * resetChangesForPath has been called on the binding or model.
1763
1870
  */
1764
1871
  function onCancel() {
1765
- _Helper.removeByPath(that.mPatchRequests, sFullPath, oPatchPromise);
1872
+ _Helper.removeByPath(that.mChangeRequests, sFullPath, oPatchPromise);
1766
1873
  // write the previous value into the cache
1767
1874
  _Helper.updateExisting(that.mChangeListeners, sEntityPath, oEntity, oOldData);
1768
1875
  }
@@ -1812,14 +1919,14 @@ sap.ui.define([
1812
1919
  bAtFront, /*mQueryOptions*/ undefined, /*vOwner*/ undefined,
1813
1920
  mergePatchRequests);
1814
1921
  oPatchPromise.$isKeepAlive = fnIsKeepAlive;
1815
- _Helper.addByPath(that.mPatchRequests, sFullPath, oPatchPromise);
1922
+ _Helper.addByPath(that.mChangeRequests, sFullPath, oPatchPromise);
1816
1923
  return SyncPromise.all([
1817
1924
  oPatchPromise,
1818
1925
  that.fetchTypes()
1819
1926
  ]).then(function (aResult) {
1820
1927
  var oPatchResult = aResult[0];
1821
1928
 
1822
- _Helper.removeByPath(that.mPatchRequests, sFullPath, oPatchPromise);
1929
+ _Helper.removeByPath(that.mChangeRequests, sFullPath, oPatchPromise);
1823
1930
  if (bSkip) {
1824
1931
  // if a PATCH is skipped, because it is merged into another, nothing to do!
1825
1932
  return;
@@ -1843,7 +1950,7 @@ sap.ui.define([
1843
1950
  onCancel();
1844
1951
  throw oError;
1845
1952
  }
1846
- _Helper.removeByPath(that.mPatchRequests, sFullPath, oPatchPromise);
1953
+ _Helper.removeByPath(that.mChangeRequests, sFullPath, oPatchPromise);
1847
1954
  if (oError.canceled) {
1848
1955
  throw oError;
1849
1956
  }
@@ -2202,23 +2309,6 @@ sap.ui.define([
2202
2309
  this.aElements.$byPredicate[_Helper.getPrivateAnnotation(oElement, "predicate")] = oElement;
2203
2310
  };
2204
2311
 
2205
- /**
2206
- * Adjusts the indices for read requests.
2207
- *
2208
- * @param {number} iIndex The index at which an element has been added or removed
2209
- * @param {number} iOffset The offset to add to the indices
2210
- *
2211
- * @private
2212
- */
2213
- _CollectionCache.prototype.adjustReadRequests = function (iIndex, iOffset) {
2214
- this.aReadRequests.forEach(function (oReadRequest) {
2215
- if (oReadRequest.iStart >= iIndex) {
2216
- oReadRequest.iStart += iOffset;
2217
- oReadRequest.iEnd += iOffset;
2218
- } // Note: no changes can happen inside *gaps*
2219
- });
2220
- };
2221
-
2222
2312
  /**
2223
2313
  * Creates an empty element for the given predicate to the cache, adds it to the cache and
2224
2314
  * returns it.
@@ -2246,6 +2336,15 @@ sap.ui.define([
2246
2336
  * @public
2247
2337
  */
2248
2338
  _CollectionCache.prototype.doReplaceWith = function (iIndex, oElement) {
2339
+ var oOldElement = this.aElements[iIndex];
2340
+
2341
+ if (oOldElement && _Helper.hasPrivateAnnotation(oOldElement, "transientPredicate")
2342
+ && !_Helper.hasPrivateAnnotation(oElement, "transientPredicate")) {
2343
+ // when replacing a created element (w/ transientPredicate), make sure the replacement
2344
+ // also *looks* like a created one (but do not overwrite existing transientPredicate!)
2345
+ _Helper.setPrivateAnnotation(oElement, "transientPredicate",
2346
+ _Helper.getPrivateAnnotation(oElement, "predicate"));
2347
+ }
2249
2348
  this.aElements[iIndex] = oElement;
2250
2349
  this.addKeptElement(oElement); // maintain $byPredicate
2251
2350
  };
@@ -2305,7 +2404,7 @@ sap.ui.define([
2305
2404
  return oSyncPromise.then(function () {
2306
2405
  // register afterwards to avoid that updateExisting fires updates before the first
2307
2406
  // response
2308
- that.registerChange(sPath, oListener);
2407
+ that.registerChangeListener(sPath, oListener);
2309
2408
  return that.drillDown(that.aElements, sPath, oGroupLock, bCreateOnDemand);
2310
2409
  });
2311
2410
  };
@@ -2343,7 +2442,8 @@ sap.ui.define([
2343
2442
  };
2344
2443
 
2345
2444
  /**
2346
- * Returns a filter that excludes all created entities in this cache's collection.
2445
+ * Returns a filter that excludes all created entities in this cache's collection (including
2446
+ * those that have been deleted on the client again).
2347
2447
  *
2348
2448
  * @returns {string|undefined}
2349
2449
  * The filter or <code>undefined</code> if there is no created entity.
@@ -2352,22 +2452,33 @@ sap.ui.define([
2352
2452
  */
2353
2453
  _CollectionCache.prototype.getFilterExcludingCreated = function () {
2354
2454
  var oElement,
2355
- sKeyFilter,
2356
2455
  aKeyFilters = [],
2357
2456
  mTypeForMetaPath,
2358
- i;
2457
+ i,
2458
+ that = this;
2459
+
2460
+ function addKeyFilter(oElement) {
2461
+ var sKeyFilter;
2462
+
2463
+ mTypeForMetaPath = mTypeForMetaPath
2464
+ || that.fetchTypes().getResult(); // Note: $metadata already read
2465
+ sKeyFilter = _Helper.getKeyFilter(oElement, that.sMetaPath, mTypeForMetaPath);
2466
+ if (sKeyFilter) {
2467
+ aKeyFilters.push(sKeyFilter);
2468
+ }
2469
+ }
2359
2470
 
2360
2471
  for (i = 0; i < this.aElements.$created; i += 1) {
2361
2472
  oElement = this.aElements[i];
2362
2473
  if (!oElement["@$ui5.context.isTransient"]) {
2363
- mTypeForMetaPath = mTypeForMetaPath
2364
- || this.fetchTypes().getResult(); // Note: $metadata already read
2365
- sKeyFilter = _Helper.getKeyFilter(oElement, this.sMetaPath, mTypeForMetaPath);
2366
- if (sKeyFilter) {
2367
- aKeyFilters.push(sKeyFilter);
2368
- }
2474
+ addKeyFilter(oElement);
2369
2475
  }
2370
2476
  }
2477
+ (this.aElements.$deleted || []).forEach(function (oDeleted) {
2478
+ if (oDeleted.created) {
2479
+ addKeyFilter(that.aElements.$byPredicate[oDeleted.predicate]);
2480
+ }
2481
+ });
2371
2482
 
2372
2483
  return aKeyFilters.length ? "not (" + aKeyFilters.sort().join(" or ") + ")" : undefined;
2373
2484
  };
@@ -2401,6 +2512,28 @@ sap.ui.define([
2401
2512
  return sQueryString;
2402
2513
  };
2403
2514
 
2515
+ /**
2516
+ * Determines the offset to <code>$skip</code> due to deleted elements in other groups.
2517
+ *
2518
+ * @param {string} sGroupId - The group ID for the read request
2519
+ * @param {number} iStart - The start index for the read
2520
+ * @returns {number} The offset
2521
+ */
2522
+ _CollectionCache.prototype.getReadOffset = function (sGroupId, iStart) {
2523
+ var iOffset = 0;
2524
+
2525
+ (this.aElements.$deleted || []).forEach(function (oDeleteInfo) {
2526
+ // if deleting in the same group, the entity is gone when the server reads
2527
+ // created-persisted entities are excluded via filter
2528
+ if (oDeleteInfo.groupId !== sGroupId && !oDeleteInfo.created
2529
+ && oDeleteInfo.index <= iStart) {
2530
+ iOffset += 1;
2531
+ }
2532
+ });
2533
+
2534
+ return iOffset;
2535
+ };
2536
+
2404
2537
  /**
2405
2538
  * Returns the resource path including the query string with $skip and $top if needed.
2406
2539
  *
@@ -2816,6 +2949,9 @@ sap.ui.define([
2816
2949
  * The number of transient elements within the given group
2817
2950
  * @param {function} [fnDataRequested]
2818
2951
  * The function is called when the back-end requests have been sent.
2952
+ * @returns {sap.ui.base.SyncPromise}
2953
+ * A promise resolving without a defined result when the request is finished and rejecting in
2954
+ * case of error
2819
2955
  * @throws {Error}
2820
2956
  * If group ID is '$cached'. The error has a property <code>$cached = true</code>
2821
2957
  *
@@ -2823,7 +2959,8 @@ sap.ui.define([
2823
2959
  */
2824
2960
  _CollectionCache.prototype.requestElements = function (iStart, iEnd, oGroupLock,
2825
2961
  iTransientElements, fnDataRequested) {
2826
- var oPromise,
2962
+ var iOffset = this.getReadOffset(oGroupLock.getGroupId(), iStart),
2963
+ oPromise,
2827
2964
  oReadRequest = {
2828
2965
  iEnd : iEnd,
2829
2966
  iStart : iStart
@@ -2833,8 +2970,9 @@ sap.ui.define([
2833
2970
  this.aReadRequests.push(oReadRequest);
2834
2971
  this.bSentRequest = true;
2835
2972
  oPromise = SyncPromise.all([
2836
- this.oRequestor.request("GET", this.getResourcePathWithQuery(iStart, iEnd), oGroupLock,
2837
- undefined, undefined, fnDataRequested),
2973
+ this.oRequestor.request("GET",
2974
+ this.getResourcePathWithQuery(iStart + iOffset, iEnd + iOffset),
2975
+ oGroupLock, undefined, undefined, fnDataRequested),
2838
2976
  this.fetchTypes()
2839
2977
  ]).then(function (aResult) {
2840
2978
  var iFiltered;
@@ -2855,6 +2993,8 @@ sap.ui.define([
2855
2993
 
2856
2994
  // Note: oPromise MUST be a SyncPromise for performance reasons, see SyncPromise#all
2857
2995
  this.fill(oPromise, iStart, iEnd);
2996
+
2997
+ return oPromise;
2858
2998
  };
2859
2999
 
2860
3000
  /**
@@ -2869,9 +3009,6 @@ sap.ui.define([
2869
3009
  * The "14.5.11 Expression edm:NavigationPropertyPath" or
2870
3010
  * "14.5.13 Expression edm:PropertyPath" strings describing which properties need to be loaded
2871
3011
  * because they may have changed due to side effects of a previous update
2872
- * @param {object} mNavigationPropertyPaths
2873
- * Hash set of collection-valued navigation property meta paths (relative to this cache's
2874
- * root) which need to be refreshed, maps string to <code>true</code>; is modified
2875
3012
  * @param {string[]} aPredicates
2876
3013
  * The key predicates of the root elements to request side effects for
2877
3014
  * @param {boolean} bSingle
@@ -2886,8 +3023,8 @@ sap.ui.define([
2886
3023
  *
2887
3024
  * @public
2888
3025
  */
2889
- _CollectionCache.prototype.requestSideEffects = function (oGroupLock, aPaths,
2890
- mNavigationPropertyPaths, aPredicates, bSingle) {
3026
+ _CollectionCache.prototype.requestSideEffects = function (oGroupLock, aPaths, aPredicates,
3027
+ bSingle) {
2891
3028
  var aElements,
2892
3029
  iMaxIndex = -1,
2893
3030
  mMergeableQueryOptions,
@@ -2902,15 +3039,13 @@ sap.ui.define([
2902
3039
 
2903
3040
  if (this.oPendingRequestsPromise) {
2904
3041
  return this.oPendingRequestsPromise.then(function () {
2905
- return that.requestSideEffects(oGroupLock, aPaths, mNavigationPropertyPaths,
2906
- aPredicates, bSingle);
3042
+ return that.requestSideEffects(oGroupLock, aPaths, aPredicates, bSingle);
2907
3043
  });
2908
3044
  }
2909
3045
 
2910
3046
  mQueryOptions = _Helper.intersectQueryOptions(
2911
3047
  Object.assign({}, this.mQueryOptions, this.mLateQueryOptions), aPaths,
2912
- this.oRequestor.getModelInterface().fetchMetadata, this.sMetaPath,
2913
- mNavigationPropertyPaths, "", true);
3048
+ this.oRequestor.getModelInterface().fetchMetadata, this.sMetaPath, "", true);
2914
3049
  if (!mQueryOptions) {
2915
3050
  return SyncPromise.resolve(); // micro optimization: use *sync.* promise which is cached
2916
3051
  }
@@ -3193,7 +3328,7 @@ sap.ui.define([
3193
3328
  fnDataRequested, undefined, this.sMetaPath));
3194
3329
  }
3195
3330
  return this.oPromise.then(function (oResult) {
3196
- that.registerChange("", oListener);
3331
+ that.registerChangeListener("", oListener);
3197
3332
  // Note: For a null value, null is returned due to "204 No Content". For $count,
3198
3333
  // "a simple primitive integer value with media type text/plain" is returned.
3199
3334
  return oResult && typeof oResult === "object" ? oResult.value : oResult;
@@ -3319,7 +3454,7 @@ sap.ui.define([
3319
3454
  if (oResult && oResult["$ui5.deleted"]) {
3320
3455
  throw new Error("Cannot read a deleted entity");
3321
3456
  }
3322
- that.registerChange(sPath, oListener);
3457
+ that.registerChangeListener(sPath, oListener);
3323
3458
  return that.drillDown(oResult, sPath, oGroupLock, bCreateOnDemand);
3324
3459
  });
3325
3460
  };
@@ -3457,9 +3592,6 @@ sap.ui.define([
3457
3592
  * The "14.5.11 Expression edm:NavigationPropertyPath" or
3458
3593
  * "14.5.13 Expression edm:PropertyPath" strings describing which properties need to be loaded
3459
3594
  * because they may have changed due to side effects of a previous update
3460
- * @param {object} mNavigationPropertyPaths
3461
- * Hash set of collection-valued navigation property meta paths (relative to this cache's
3462
- * root) which need to be refreshed, maps string to <code>true</code>; is modified
3463
3595
  * @param {string} [sResourcePath=this.sResourcePath]
3464
3596
  * A resource path relative to the service URL; it must not contain a query string
3465
3597
  * @returns {Promise|sap.ui.base.SyncPromise}
@@ -3470,8 +3602,7 @@ sap.ui.define([
3470
3602
  *
3471
3603
  * @public
3472
3604
  */
3473
- _SingleCache.prototype.requestSideEffects = function (oGroupLock, aPaths,
3474
- mNavigationPropertyPaths, sResourcePath) {
3605
+ _SingleCache.prototype.requestSideEffects = function (oGroupLock, aPaths, sResourcePath) {
3475
3606
  var mMergeableQueryOptions,
3476
3607
  mQueryOptions,
3477
3608
  oResult,
@@ -3482,8 +3613,7 @@ sap.ui.define([
3482
3613
 
3483
3614
  mQueryOptions = this.oPromise && _Helper.intersectQueryOptions(
3484
3615
  Object.assign({}, this.mQueryOptions, this.mLateQueryOptions), aPaths,
3485
- this.oRequestor.getModelInterface().fetchMetadata,
3486
- this.sMetaPath, mNavigationPropertyPaths);
3616
+ this.oRequestor.getModelInterface().fetchMetadata, this.sMetaPath);
3487
3617
  if (!mQueryOptions) {
3488
3618
  return SyncPromise.resolve();
3489
3619
  }