fieldEncoder.encode(new InstanceStore()
{
@Override
public Key toKey(Object instance, Object parent)
{
Key key = cache.getKey(instance);
if (key == null)
throw new IllegalArgumentException("Must filter on instances from same ObjectStoreSession");
return key;
}
}, ConvertUtils.convert(v, f.getType()), new PropertyStore()
{
@Override
public void setProperty(String key, Object value, boolean index)
{
if(isMultiple)
{
List<Object> list = ObjectUtils.cast(properties.get(key));
if(list == null)
{
list = Lists.newArrayList();
properties.put(key, list);
}
list.add(value);
}
else
{
properties.put(key, value);
}
}
});
if (properties.size() > 1 && gop != FilterOperator.EQUAL)
throw new IllegalArgumentException("Cannot filter embedded types with operator: " + gop);
for (Entry<String, Object> entry : properties.entrySet())
query.addFilter(entry.getKey(), gop, entry.getValue());
return this;
}
@Override
public Find<T> filterBetween(String field, Object lower, Object upper)
{
return filterBetween(field, lower, upper, true, false);
}
@Override
public Find<T> filterBetween(String field, Object lower, Object upper, boolean includeBottom, boolean includeTop)
{
Find.Op lowerOp, upperOp;
if (includeBottom)
lowerOp = Find.Op.GreaterThanOrEqualTo;
else
lowerOp = Find.Op.GreaterThan;
if (includeTop)
upperOp = Find.Op.LessThanOrEqualTo;
else
upperOp = Find.Op.LessThan;
filter(field, lowerOp, lower);
filter(field, upperOp, upper);
return this;
}
@Override
public Find<T> filterBeginsWith(String field, String value)
{
filterBetween(field, value, value + "\uFFFD");
return this;
}
@Override
public Find<T> ancestor(Object ancestor)
{
query.setAncestor(cache.getKey(ancestor));
return this;
}
int start = 0;
@Override
public Find<T> start(int offset)
{
this.start = offset;
return this;
}
int limit = Integer.MAX_VALUE;
@Override
public Find<T> limit(int count)
{
limit = count;
return this;
}
private boolean activated = true;
@Override
public Find<T> unactivated()
{
activated = false;
query.setKeysOnly();
return this;
}
private boolean refresh = false;
@Override
public Find<T> refresh()
{
refresh = true;
return this;
}
private int retries = 5;
@Override
public Find<T> retries(int count)
{
retries = count;
return this;
}
private List<String> activatePatterns = Lists.newArrayList();
@Override
public Find<T> activate(String... patterns)
{
activatePatterns.addAll(Arrays.asList(patterns));
return this;
}
@Override
public Find<T> activate(int levels)
{
return activate(ActivationFilter.getLevelActivationFilter(levels));
}
@Override
public Iterable<T> now()
{
return FutureUtils.safeGet(later());
}
@Override
public Future<Iterable<T>> later()
{
final Iterable<T> result = queryNow(); // get the query going now
return new ImmediateFuture<Iterable<T>>()
{
@Override
public Iterable<T> get()
{
return result;
}
};
}
private Iterable<T> queryNow()
{
return toEntityIterable(service.prepare(query).asIterable(withOffset(start).limit(limit)));
}
private Iterable<T> toEntityIterable(final Iterable<Entity> iterable)
{
return new Iterable<T>()
{
@Override
public Iterator<T> iterator()
{
return new Iterator<T>()
{
Iterator<Entity> nested = iterable.iterator();
ActivationFilter filter = ActivationFilter.compile(activatePatterns);
@Override
public boolean hasNext()
{
return nested.hasNext();
}
@SuppressWarnings("unchecked")
@Override
public T next()
{
Entity entity = nested.next();
if (activated)
{
return toObject(type, entity, refresh, retries, filter);
}
else
{
Key key = entity.getKey();
T object = (T) cache.getKey(key);
if (object == null)
object = createShell(type, key);
return object;
}