OfflineQueryLogic { static <T extends ParseObject> void sort(List<T> results, ParseQuery.State<T> state) throws ParseException { final List<String> keys = state.order(); 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)); } } } 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 (keys.size() == 0 && mutableNearSphereKey == null) { return; } 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); } 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; } }); } OfflineQueryLogic(OfflineStore store);   }
@Test public void testSortInvalidKey() throws ParseException { ParseQuery.State<ParseObject> query = new ParseQuery.State.Builder<>("TestObject") .addAscendingOrder("_test") .build(); thrown.expect(ParseException.class); OfflineQueryLogic.sort(null, query); }
@Test public void testSortWithNoOrder() throws ParseException { ParseQuery.State<ParseObject> query = new ParseQuery.State.Builder<>("TestObject") .build(); OfflineQueryLogic.sort(null, query); }
@Test public void testSortWithGeoQuery() throws ParseException { ParseGeoPoint fb = new ParseGeoPoint(37.481689f, -122.154949f); ParseQuery.State<ParseObject> query = new ParseQuery.State.Builder<>("TestObject") .whereNear("point", fb) .build(); List<ParseObject> objects = new ArrayList<>(); ParseObject object; object = new ParseObject("TestObject"); object.put("name", "sf"); object.put("point", new ParseGeoPoint(37.774929f, -122.419416f)); objects.add(object); object = new ParseObject("TestObject"); object.put("name", "ny"); object.put("point", new ParseGeoPoint(40.712784f, -74.005941f)); objects.add(object); object = new ParseObject("TestObject"); object.put("name", "mpk"); object.put("point", new ParseGeoPoint(37.452960f, -122.181725f)); objects.add(object); OfflineQueryLogic.sort(objects, query); assertEquals("mpk", objects.get(0).getString("name")); assertEquals("sf", objects.get(1).getString("name")); assertEquals("ny", objects.get(2).getString("name")); }
@Test public void testSortDescending() throws ParseException { ParseQuery.State<ParseObject> query = new ParseQuery.State.Builder<>("TestObject") .addDescendingOrder("name") .build(); List<ParseObject> objects = new ArrayList<>(); ParseObject object; object = new ParseObject("TestObject"); object.put("name", "grantland"); objects.add(object); object = new ParseObject("TestObject"); object.put("name", "nikita"); objects.add(object); object = new ParseObject("TestObject"); object.put("name", "listiarso"); objects.add(object); OfflineQueryLogic.sort(objects, query); assertEquals("nikita", objects.get(0).getString("name")); assertEquals("listiarso", objects.get(1).getString("name")); assertEquals("grantland", objects.get(2).getString("name")); }
@Test public void testQuerySortNumber() throws ParseException { ParseQuery.State<ParseObject> query = new ParseQuery.State.Builder<>("TestObject") .addAscendingOrder("key") .build(); List<ParseObject> results = generateParseObjects("key", new Object[]{ 8, 7.0, 6.0f, (long) 5 }); OfflineQueryLogic.sort(results, query); int last = 0; for (ParseObject result : results) { int current = result.getInt("key"); assertTrue(current > last); last = current; } }
@Test public void testQuerySortNull() throws ParseException { ParseQuery.State<ParseObject> query = new ParseQuery.State.Builder<>("TestObject") .addAscendingOrder("key") .build(); List<ParseObject> results = generateParseObjects("key", new Object[]{ null, "value", null }); OfflineQueryLogic.sort(results, query); assertEquals(0, results.get(0).getInt("id")); assertEquals(2, results.get(1).getInt("id")); assertEquals(1, results.get(2).getInt("id")); }
@Test public void testQuerySortDifferentTypes() throws ParseException { ParseQuery.State<ParseObject> query = new ParseQuery.State.Builder<>("TestObject") .addAscendingOrder("key") .build(); List<ParseObject> results = generateParseObjects("key", new Object[]{ "string", 5 }); thrown.expect(IllegalArgumentException.class); OfflineQueryLogic.sort(results, query); }