package org.ovirt.engine.ui.userportal.uicommon.model; import java.util.HashMap; import java.util.List; import java.util.Map; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.ui.common.auth.CurrentUser; import org.ovirt.engine.ui.common.presenter.popup.DefaultConfirmationPopupPresenterWidget; import org.ovirt.engine.ui.uicommonweb.models.userportal.AbstractUserPortalListModel; import org.ovirt.engine.ui.uicommonweb.models.userportal.UserPortalItemModel; import com.google.gwt.event.shared.EventBus; import com.google.inject.Provider; /** * Base class for {@link org.ovirt.engine.ui.uicommonweb.models.userportal.AbstractUserPortalListModel} providers with {@linkplain #itemsChanged data update optimization}. * * @param <M> * List model type. */ public abstract class AbstractUserPortalListProvider<M extends AbstractUserPortalListModel> extends UserPortalDataBoundModelProvider<UserPortalItemModel, M> implements UserPortalSearchableTableModelProvider<UserPortalItemModel, M> { private List<UserPortalItemModel> currentItems; /** * Force an update of the view regardless of if anything has changed. */ private boolean forceUpdate = false; public AbstractUserPortalListProvider(EventBus eventBus, Provider<DefaultConfirmationPopupPresenterWidget> defaultConfirmPopupProvider, CurrentUser user) { super(eventBus, defaultConfirmPopupProvider, user); } @Override protected void updateDataProvider(List<UserPortalItemModel> items) { // First data update if (currentItems == null) { currentItems = items; super.updateDataProvider(items); } // Subsequent data update, with item change else if (forceUpdate || itemsChanged(items, currentItems)) { clearReferences(); super.updateDataProvider(items); } // Subsequent data update, without item change else { retainSelectedItems(); } forceUpdate = false; currentItems = items; } private void clearReferences() { if (currentItems != null) { for(UserPortalItemModel itemModel: currentItems) { itemModel.clearReferences(); } } } @Override public void clearCurrentItems() { clearReferences(); currentItems = null; } /** * Instead of clearing the items in the model, just mark a flag that forces the * view to update the grid when updateProvider is called. */ @Override public void onManualRefresh() { forceUpdate = true; } /** * Returns {@code true} if there is a change between {@code newItems} and {@code oldItems}, {@code false} otherwise. */ boolean itemsChanged(List<UserPortalItemModel> newItems, List<UserPortalItemModel> oldItems) { Map<Guid, UserPortalItemModel> oldItemMap = new HashMap<>(oldItems.size()); for (UserPortalItemModel oldItem : oldItems) { oldItemMap.put(oldItem.getId(), oldItem); } for (UserPortalItemModel newItem : newItems) { Guid newItemId = newItem.getId(); UserPortalItemModel oldItem = oldItemMap.get(newItemId); // Return true in case of new item or item change if (oldItem == null || !newItem.entityStateEqualTo(oldItem)) { return true; } oldItemMap.remove(newItemId); } // Return true in case there are no more old items left (to remove) return !oldItemMap.isEmpty(); } }