package com.google.sitebricks.persist; import java.util.List; /** * @author dhanji@gmail.com (Dhanji R. Prasanna) */ public interface EntityQuery<T> { <E> Clause<T> where(E field, FieldMatcher<E> matcher); public static interface Clause<T> { <E> Clause and(E field, FieldMatcher<E> matcher); EntityQuery<T> or(); List<T> list(); List<T> list(int limit); List<T> list(int offset, int limit); /** * Delete all matching persistent objects from the underlying datastore. Useful * for bulk deletions, only datastores that support this natively will work. */ <T> void remove(); } public static class FieldMatcher<E> { public final Kind kind; public final E low, high; public final double threshold; protected FieldMatcher(Kind kind, E value) { this(kind, value, null, -1.0); } protected FieldMatcher(Kind kind, E low, E high) { this(kind, low, high, -1.0); } protected FieldMatcher(Kind kind, E low, E high, double threshold) { this.kind = kind; this.low = low; this.high = high; this.threshold = threshold; } public static <T> FieldMatcher<T> is(T t) { return new FieldMatcher<T>(Kind.IS, t); } public static <T> FieldMatcher<T> not(T t) { return new FieldMatcher<T>(Kind.NOT, t); } public static FieldMatcher<String> like(String t) { return new FieldMatcher<String>(Kind.LIKE, t); } /** * Adds fuzzy query constraint on the given string matched against a fuzziness threshold. * For example: * <pre> * similarTo("cafe", 1.0); * </pre> * * May return "cate", "café", "late" etc., depending on the threshold. The threshold is an * abstract specifier, which the underlying datastore may choose to incorporate into its * algorithm or ignore completely. * <p> * A value of 0 of the threshold indicates an exact match, whereas 1.0 indicates an maximally * expansive, fuzzy match. * </p> */ public static <String> FieldMatcher<String> similarTo(String t, double threshold) { if (threshold > 1.0 || threshold < 0.0) throw new IllegalArgumentException("Similarity threshold must be between [0 - 1]"); return new FieldMatcher<String>(Kind.SIMILAR_TO, t, null, threshold); } public static <T> FieldMatcher<T> between(T t1, T t2) { return new FieldMatcher<T>(Kind.BETWEEN, t1, t2); } public static <T> FieldMatcher<T> above(T t) { return new FieldMatcher<T>(Kind.ABOVE, t); } public static <T> FieldMatcher<T> below(T t) { return new FieldMatcher<T>(Kind.BELOW, t); } public static <T> FieldMatcher<T> aboveIncluding(T t) { return new FieldMatcher<T>(Kind.ABOVE_INCLUDING, t); } public static <T> FieldMatcher<T> belowIncluding(T t) { return new FieldMatcher<T>(Kind.BELOW_INCLUDING, t); } public static enum Kind { IS, NOT, LIKE, SIMILAR_TO, ABOVE, BELOW, ABOVE_INCLUDING, BELOW_INCLUDING, BETWEEN, CUSTOM, } } }