package com.bagri.xdm.access.coherence.impl; import java.util.Arrays; import java.util.Comparator; import java.util.ConcurrentModificationException; import java.util.Map; import java.util.Set; import com.tangosol.net.BackingMapContext; import com.tangosol.net.cache.BackingMapBinaryEntry; import com.tangosol.util.Binary; import com.tangosol.util.BinaryEntry; import com.tangosol.util.Filter; import com.tangosol.util.ImmutableArrayList; import com.tangosol.util.InvocableMapHelper; import com.tangosol.util.ObservableMap; import com.tangosol.util.SubSet; import com.tangosol.util.comparator.EntryComparator; import com.tangosol.util.comparator.SafeComparator; import com.tangosol.util.filter.AlwaysFilter; import com.tangosol.util.filter.IndexAwareFilter; import com.tangosol.util.filter.LimitFilter; public class QueryHelper { public static final QueryHelper INSTANCE = new QueryHelper(); @SuppressWarnings({ "unchecked" }) public <T> Set<T> query(BackingMapContext backingMapContext, Filter filter, boolean shouldReturnEntries, boolean shouldSort, Comparator comparator) { Map backingMap = backingMapContext.getBackingMap(); Map indexMap = backingMapContext.getIndexMap(); boolean matchAll = AlwaysFilter.INSTANCE.equals(filter); Filter remainingFilter = null; Object[] results; if (matchAll || indexMap == null || !(filter instanceof IndexAwareFilter)) { results = backingMap.keySet().toArray(); } else { Set filteredKeys = new SubSet(backingMap.keySet()); try { remainingFilter = ((IndexAwareFilter) filter).applyIndex(indexMap, filteredKeys); } catch (ConcurrentModificationException e) { filteredKeys = new SubSet(new ImmutableArrayList(backingMap.keySet().toArray())); remainingFilter = ((IndexAwareFilter) filter).applyIndex(indexMap, filteredKeys); } results = filteredKeys.toArray(); matchAll = (remainingFilter == null); } int numberOfResults = 0; if (matchAll && !shouldReturnEntries) { numberOfResults = results.length; } else { for (Object key : results) { Object value = backingMap.get(key); if (value == null && !backingMap.containsKey(key)) { continue; } Map.Entry entry = new QueryBinaryEntry((Binary) key, (Binary) value, null, backingMapContext); if (matchAll || InvocableMapHelper.evaluateEntry(remainingFilter, entry)) { results[numberOfResults++] = shouldReturnEntries ? entry : key; } } } boolean isLimitFilter = filter instanceof LimitFilter; if (isLimitFilter || (shouldReturnEntries && shouldSort)) { if (numberOfResults < results.length) { Object[] copy = new Object[numberOfResults]; System.arraycopy(results, 0, copy, 0, numberOfResults); results = copy; } if (shouldReturnEntries && shouldSort) { if (comparator == null) { comparator = SafeComparator.INSTANCE; } Arrays.sort(results, new EntryComparator(comparator)); } else if (shouldSort) { Arrays.sort(results, comparator); } if (isLimitFilter) { LimitFilter limitFilter = (LimitFilter) filter; limitFilter.setComparator(null); results = limitFilter.extractPage(results); numberOfResults = results.length; limitFilter.setComparator(comparator); } } return new ImmutableArrayList(results, 0, numberOfResults).getSet(); } public <T> Set<T> keySet(BinaryEntry entry, String cacheName, Filter filter) { return keySet(entry, cacheName, filter, false, null); } public <T> Set<T> keySet(BinaryEntry entry, String cacheName, Filter filter, boolean shouldSort, Comparator comparator) { BackingMapContext backingMapContext = entry.getContext().getBackingMapContext(cacheName); return query(backingMapContext, filter, false, shouldSort, comparator); } public Set entrySet(BinaryEntry entry, String cacheName, Filter filter) { return entrySet(entry, cacheName, filter, false, null); } public Set entrySet(BinaryEntry entry, String cacheName, Filter filter, boolean shouldSort, Comparator comparator) { BackingMapContext backingMapContext = entry.getContext().getBackingMapContext(cacheName); return query(backingMapContext, filter, true, shouldSort, comparator); } public <T> Set<T> entrySet(BackingMapContext backingMapContext, Filter filter) { return query(backingMapContext, filter, true, false, null); } private class QueryBinaryEntry extends BackingMapBinaryEntry { private BackingMapContext backingMapContext; private QueryBinaryEntry(Binary key, Binary value, Binary originalValue, BackingMapContext backingMapContext) { super(key, value, originalValue, backingMapContext .getManagerContext()); this.backingMapContext = backingMapContext; } @Override public ObservableMap getBackingMap() { return backingMapContext.getBackingMap(); } @Override public BackingMapContext getBackingMapContext() { return backingMapContext; } @Override public boolean isReadOnly() { return false; //true; } @Override public boolean isPresent() { return true; } } }