/** * GRANITE DATA SERVICES * Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * *** * * Community License: GPL 3.0 * * This file is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * This file is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * *** * * Available Commercial License: GraniteDS SLA 1.0 * * This is the appropriate option if you are creating proprietary * applications and you are not prepared to distribute and share the * source code of your application under the GPL v3 license. * * Please visit http://www.granitedataservices.com/license for more * details. */ package org.granite.client.tide.collection; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.PreDestroy; import javax.inject.Named; import org.granite.binding.collection.CollectionChangeEvent; import org.granite.binding.collection.CollectionChangeEvent.Kind; import org.granite.binding.collection.CollectionChangeListener; import org.granite.binding.collection.CollectionChangeSupport; import org.granite.binding.collection.ObservableList; import org.granite.binding.collection.ObservableListWrapper; import org.granite.binding.collection.ObservableMap; import org.granite.binding.collection.ObservableStringMapWrapper; import org.granite.client.tide.server.Component; import org.granite.client.tide.server.ServerSession; import org.granite.client.tide.server.TideRpcEvent; /** * @author William DRAI */ @Named public class PagedQuery<E, F> extends AbstractPagedCollection<E, F> implements ObservableList<E> { protected CollectionChangeSupport ccs = new CollectionChangeSupport(this); private List<E> internalWrappedList = new ArrayList<E>(); protected ObservableList<E> wrappedList; private Map<String, Object> internalFilterMap; private ObservableMap<String, Object> filterMap; private F filter; protected PagedQuery() { // CDI proxying... } public PagedQuery(ServerSession serverSession) { super(serverSession); initWrappedList(); } public PagedQuery(Component remoteComponent, String methodName, int maxResults) { super(remoteComponent, methodName, maxResults); initWrappedList(); } public PagedQuery(Component remoteComponent, PageFilterFinder<E> finder, int maxResults) { super(remoteComponent, finder, maxResults); initWrappedList(); } public PagedQuery(Component remoteComponent, SimpleFilterFinder<E> finder, int maxResults) { super(remoteComponent, finder, maxResults); initWrappedList(); } @Override protected List<E> getInternalWrappedList() { return internalWrappedList; } @Override protected List<E> getWrappedList() { return wrappedList; } public void addCollectionChangeListener(CollectionChangeListener listener) { ccs.addCollectionChangeListener(listener); } public void removeCollectionChangeListener(CollectionChangeListener listener) { ccs.removeCollectionChangeListener(listener); } private void initWrappedList() { wrappedList = new ObservableListWrapper<E>(internalWrappedList); wrappedList.addCollectionChangeListener(new WrappedListCollectionChangeListener()); } @Override protected void initFilter() { this.internalFilterMap = new HashMap<String, Object>(); this.filterMap = new ObservableStringMapWrapper<Object>(Collections.synchronizedMap(internalFilterMap)); this.filterMap.addCollectionChangeListener(new CollectionChangeListener() { @Override public void collectionChange(CollectionChangeEvent event) { fullRefresh = true; filterRefresh = true; } }); this.filter = null; } @SuppressWarnings("unchecked") public F getFilter() { if (filter != null) return filter; try { return (F)filterMap; } catch (ClassCastException e) { return null; } } public void setFilter(F filter) { if (filter == null) internalFilterMap.clear(); else this.filter = filter; } @SuppressWarnings("unchecked") @Override protected F cloneFilter() { if (filter != null) return filter; // Copy filter map to avoid concurrent modifications synchronized (internalFilterMap) { return (F)new HashMap<String, Object>(internalFilterMap); } } @Override @PreDestroy public void clear() { super.clear(); ccs = new CollectionChangeSupport(this); } @Override public Object[] toArray() { throw new UnsupportedOperationException(); } @Override public <T> T[] toArray(T[] a) { throw new UnsupportedOperationException(); } public void firePageChange(TideRpcEvent event, int previousFirst, int previousLast, List<E> savedSnapshot) { ccs.fireCollectionChangeEvent(Kind.PAGE_CHANGE, event, null); } public class WrappedListCollectionChangeListener implements CollectionChangeListener { @Override public void collectionChange(CollectionChangeEvent event) { ccs.fireCollectionChangeEvent(event.getKind(), event.getKey(), event.getValues()); } } }