use of com.parse.ParseQuery.KeyConstraints in project Parse-SDK-Android by ParsePlatform.
the class OfflineQueryLogic method sort.
/**
* Sorts the given array based on the parameters of the given query.
*/
/* package */
static <T extends ParseObject> void sort(List<T> results, ParseQuery.State<T> state) throws ParseException {
final List<String> keys = state.order();
// Do some error checking just for maximum compatibility with the server.
for (String key : state.order()) {
if (!key.matches("^-?[A-Za-z][A-Za-z0-9_]*$")) {
if (!"_created_at".equals(key) && !"_updated_at".equals(key)) {
throw new ParseException(ParseException.INVALID_KEY_NAME, String.format("Invalid key name: \"%s\".", key));
}
}
}
// See if there's a $nearSphere constraint that will override the other sort parameters.
String mutableNearSphereKey = null;
ParseGeoPoint mutableNearSphereValue = null;
for (String queryKey : state.constraints().keySet()) {
Object queryKeyConstraints = state.constraints().get(queryKey);
if (queryKeyConstraints instanceof KeyConstraints) {
KeyConstraints keyConstraints = (KeyConstraints) queryKeyConstraints;
if (keyConstraints.containsKey("$nearSphere")) {
mutableNearSphereKey = queryKey;
mutableNearSphereValue = (ParseGeoPoint) keyConstraints.get("$nearSphere");
}
}
}
final String nearSphereKey = mutableNearSphereKey;
final ParseGeoPoint nearSphereValue = mutableNearSphereValue;
// If there's nothing to sort based on, then don't do anything.
if (keys.size() == 0 && mutableNearSphereKey == null) {
return;
}
/*
* TODO(klimt): Test whether we allow dotting into objects for sorting.
*/
Collections.sort(results, new Comparator<T>() {
@Override
public int compare(T lhs, T rhs) {
if (nearSphereKey != null) {
ParseGeoPoint lhsPoint;
ParseGeoPoint rhsPoint;
try {
lhsPoint = (ParseGeoPoint) getValue(lhs, nearSphereKey);
rhsPoint = (ParseGeoPoint) getValue(rhs, nearSphereKey);
} catch (ParseException e) {
throw new RuntimeException(e);
}
// GeoPoints can't be null if there's a $nearSphere.
double lhsDistance = lhsPoint.distanceInRadiansTo(nearSphereValue);
double rhsDistance = rhsPoint.distanceInRadiansTo(nearSphereValue);
if (lhsDistance != rhsDistance) {
return (lhsDistance - rhsDistance > 0) ? 1 : -1;
}
}
for (String key : keys) {
boolean descending = false;
if (key.startsWith("-")) {
descending = true;
key = key.substring(1);
}
Object lhsValue;
Object rhsValue;
try {
lhsValue = getValue(lhs, key);
rhsValue = getValue(rhs, key);
} catch (ParseException e) {
throw new RuntimeException(e);
}
int result;
try {
result = compareTo(lhsValue, rhsValue);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("Unable to sort by key %s.", key), e);
}
if (result != 0) {
return descending ? -result : result;
}
}
return 0;
}
});
}
use of com.parse.ParseQuery.KeyConstraints in project Parse-SDK-Android by ParsePlatform.
the class OfflineQueryLogic method createMatcher.
/**
* Returns a ConstraintMatcher that return true iff the object matches QueryConstraints. This
* takes in a SQLiteDatabase connection because SQLite is finicky about nesting connections, so we
* want to reuse them whenever possible.
*/
private <T extends ParseObject> ConstraintMatcher<T> createMatcher(ParseUser user, QueryConstraints queryConstraints) {
// Make a list of all the matchers to AND together.
final ArrayList<ConstraintMatcher<T>> matchers = new ArrayList<>();
for (final String key : queryConstraints.keySet()) {
final Object queryConstraintValue = queryConstraints.get(key);
if (key.equals("$or")) {
/*
* A set of queries to be OR-ed together.
*/
@SuppressWarnings("unchecked") ConstraintMatcher<T> matcher = createOrMatcher(user, (ArrayList<QueryConstraints>) queryConstraintValue);
matchers.add(matcher);
} else if (queryConstraintValue instanceof KeyConstraints) {
/*
* It's a set of constraints that should be AND-ed together.
*/
KeyConstraints keyConstraints = (KeyConstraints) queryConstraintValue;
for (String operator : keyConstraints.keySet()) {
final Object keyConstraintValue = keyConstraints.get(operator);
ConstraintMatcher<T> matcher = createMatcher(user, operator, keyConstraintValue, key, keyConstraints);
matchers.add(matcher);
}
} else if (queryConstraintValue instanceof RelationConstraint) {
/*
* It's a $relatedTo constraint.
*/
final RelationConstraint relation = (RelationConstraint) queryConstraintValue;
matchers.add(new ConstraintMatcher<T>(user) {
@Override
public Task<Boolean> matchesAsync(T object, ParseSQLiteDatabase db) {
return Task.forResult(relation.getRelation().hasKnownObject(object));
}
});
} else {
/*
* It's not a set of constraints, so it's just a value to compare against.
*/
matchers.add(new ConstraintMatcher<T>(user) {
@Override
public Task<Boolean> matchesAsync(T object, ParseSQLiteDatabase db) {
Object objectValue;
try {
objectValue = getValue(object, key);
} catch (ParseException e) {
return Task.forError(e);
}
return Task.forResult(matchesEqualConstraint(queryConstraintValue, objectValue));
}
});
}
}
/*
* Now AND together the constraints for each key.
*/
return new ConstraintMatcher<T>(user) {
@Override
public Task<Boolean> matchesAsync(final T object, final ParseSQLiteDatabase db) {
Task<Boolean> task = Task.forResult(true);
for (final ConstraintMatcher<T> matcher : matchers) {
task = task.onSuccessTask(new Continuation<Boolean, Task<Boolean>>() {
@Override
public Task<Boolean> then(Task<Boolean> task) throws Exception {
if (!task.getResult()) {
return task;
}
return matcher.matchesAsync(object, db);
}
});
}
return task;
}
};
}
Aggregations