json.put(KEY_CLASS_NAME, state.className()); if (state.objectId() != null) { json.put(KEY_OBJECT_ID, state.objectId()); if (state.createdAt() > 0) { json.put(KEY_CREATED_AT, ParseDateFormat.getInstance().format(new Date(state.createdAt()))); if (state.updatedAt() > 0) { json.put(KEY_UPDATED_AT, ParseDateFormat.getInstance().format(new Date(state.updatedAt()))); for (String key : state.keySet()) { Object value = state.get(key); json.put(key, objectEncoder.encode(value)); json.put(KEY_COMPLETE, state.isComplete()); json.put(KEY_IS_DELETING_EVENTUALLY, isDeletingEventually); JSONArray availableKeys = new JSONArray(state.availableKeys()); json.put(KEY_SELECTED_KEYS, availableKeys);
static ParseObject createFromParcel(Parcel source, ParseParcelDecoder decoder) { String className = source.readString(); String objectId = source.readByte() == 1 ? source.readString() : null; // Create empty object (might be the same instance if LDS is enabled) // and pass to decoder before unparceling child objects in State ParseObject object = createWithoutData(className, objectId); if (decoder instanceof ParseObjectParcelDecoder) { ((ParseObjectParcelDecoder) decoder).addKnownObject(object); } State state = State.createFromParcel(source, decoder); object.setState(state); if (source.readByte() == 1) object.localId = source.readString(); if (source.readByte() == 1) object.isDeleted = true; // If object.ldsEnabledWhenParceling is true, we got this from OfflineStore. // There is no need to restore operations in that case. boolean restoreOperations = !object.ldsEnabledWhenParceling; ParseOperationSet set = ParseOperationSet.fromParcel(source, decoder); if (restoreOperations) { for (String key : set.keySet()) { ParseFieldOperation op = set.get(key); object.performOperation(key, op); // Update ops and estimatedData } } Bundle bundle = source.readBundle(ParseObject.class.getClassLoader()); object.onRestoreInstanceState(bundle); return object; }
if (objectId != null) dest.writeString(objectId); state.writeToParcel(dest, encoder); dest.writeByte(localId != null ? (byte) 1 : 0); if (localId != null) dest.writeString(localId);
try { State.Init<?> builder = state.newBuilder(); if (completeData) { builder.clear(); builder.isComplete(state.isComplete() || completeData);
assertEquals(createAtLong, newState.createdAt()); assertEquals(updateAtLong, newState.updatedAt()); assertEquals("testObjectId", newState.objectId()); assertFalse(newState.isComplete());
for (String key : state.keySet()) { Object object = state.get(key); dataJSON.put(key, encoder.encode(object)); if (state.createdAt() > 0) { dataJSON.put(KEY_CREATED_AT, ParseDateFormat.getInstance().format(new Date(state.createdAt()))); if (state.updatedAt() > 0) { dataJSON.put(KEY_UPDATED_AT, ParseDateFormat.getInstance().format(new Date(state.updatedAt()))); if (state.objectId() != null) { dataJSON.put(KEY_OBJECT_ID, state.objectId()); objectJSON.put(KEY_CLASS_NAME, state.className()); } catch (JSONException e) { throw new RuntimeException("could not serialize object to JSON");
new ParseObject.State.Builder("Test"), json, ParseDecoder.get()).build(); assertEquals("wnAiJVI3ra", state.objectId()); assertEquals("bar", state.get("foo")); assertEquals(date.getTime(), state.createdAt()); assertEquals(((ParseObject) state.get("child")).getObjectId(), childObject.getObjectId()); state = coder.decode( new ParseObject.State.Builder("Test"), json, ParseDecoder.get()).build(); assertEquals("wnAiJVI3ra", state.objectId());
long dateLong = ParseDateFormat.getInstance().parse(objectJSON.getString("createdAt")).getTime(); assertEquals(dateLong, object.getState().createdAt()); dateLong = ParseDateFormat.getInstance().parse(objectJSON.getString("updatedAt")).getTime(); assertEquals(dateLong, object.getState().updatedAt()); assertEquals(objectJSON.getString("objectId"), object.getObjectId()); assertEquals(objectJSON.getString("sessionToken"), object.get("sessionToken")); dateLong = ParseDateFormat.getInstance().parse(objectAgainJSON.getString("createdAt")).getTime(); assertEquals(dateLong, objectAgain.getState().createdAt()); dateLong = ParseDateFormat.getInstance().parse(objectAgainJSON.getString("updatedAt")).getTime(); assertEquals(dateLong, objectAgain.getState().updatedAt()); assertEquals(objectAgainJSON.getString("objectId"), objectAgain.getObjectId()); assertEquals(objectAgainJSON.getString("sessionToken"), objectAgain.get("sessionToken"));
/** * Converts a {@code ParseObject.State} to REST JSON for saving. * <p> * Only dirty keys from {@code operations} are represented in the data. Non-dirty keys such as * {@code updatedAt}, {@code createdAt}, etc. are not included. * * @param state {@link ParseObject.State} of the type of {@link ParseObject} that will be returned. * Properties are completely ignored. * @param operations Dirty operations that are to be saved. * @param encoder Encoder instance that will be used to encode the request. * @return A REST formatted {@link JSONObject} that will be used for saving. */ public <T extends ParseObject.State> JSONObject encode( T state, ParseOperationSet operations, ParseEncoder encoder) { JSONObject objectJSON = new JSONObject(); try { // Serialize the data for (String key : operations.keySet()) { ParseFieldOperation operation = operations.get(key); objectJSON.put(key, encoder.encode(operation)); // TODO(grantland): Use cached value from hashedObjects if it's a set operation. } if (state.objectId() != null) { objectJSON.put(KEY_OBJECT_ID, state.objectId()); } } catch (JSONException e) { throw new RuntimeException("could not serialize object to JSON"); } return objectJSON; }
@Test public void testDecodeSuccessWithOldFormatJson() throws Exception { Date createAt = new Date(1000); Date updateAt = new Date(2000); String createAtStr = ParseImpreciseDateFormat.getInstance().format(createAt); String updateAtStr = ParseImpreciseDateFormat.getInstance().format(updateAt); JSONObject pointerJson = new JSONObject(); JSONArray innerObjectJson = new JSONArray() .put(0, "innerObject") .put(1, "innerObjectId"); pointerJson.put("inner", innerObjectJson); JSONObject oldObjectJson = new JSONObject() .put(KEY_OLD_OBJECT_ID, "objectId") .put(KEY_OLD_CREATED_AT, createAtStr) .put(KEY_OLD_UPDATED_AT, updateAtStr) .put(KEY_OLD_POINTERS, pointerJson); ParseObjectCurrentCoder coder = ParseObjectCurrentCoder.get(); ParseObject.State.Builder builder = coder.decode(new ParseObject.State.Builder("Test"), oldObjectJson, ParseDecoder.get()); // We use the builder to build a state to verify the content in the builder ParseObject.State state = builder.build(); assertEquals(createAt.getTime(), state.createdAt()); assertEquals(updateAt.getTime(), state.updatedAt()); assertEquals("objectId", state.objectId()); ParseObject innerObject = (ParseObject) state.get("inner"); assertEquals("innerObject", innerObject.getClassName()); assertEquals("innerObjectId", innerObject.getObjectId()); }
@Test public void testSaveAsync() throws Exception { // Make mock response and client JSONObject mockResponse = new JSONObject(); String createAtStr = "2015-08-09T22:15:13.460Z"; long createAtLong = ParseDateFormat.getInstance().parse(createAtStr).getTime(); String updateAtStr = "2015-08-09T22:15:13.497Z"; long updateAtLong = ParseDateFormat.getInstance().parse(updateAtStr).getTime(); mockResponse.put("createdAt", createAtStr); mockResponse.put("objectId", "testObjectId"); mockResponse.put("updatedAt", updateAtStr); ParseHttpClient restClient = ParseTestUtils.mockParseHttpClientWithResponse(mockResponse, 200, "OK"); // Make test state ParseObject object = new ParseObject("Test"); object.put("key", "value"); NetworkObjectController controller = new NetworkObjectController(restClient); ParseObject.State newState = ParseTaskUtils.wait(controller.saveAsync( object.getState(), object.startSave(), "sessionToken", ParseDecoder.get())); assertEquals(createAtLong, newState.createdAt()); assertEquals(updateAtLong, newState.updatedAt()); assertEquals("testObjectId", newState.objectId()); assertFalse(newState.isComplete()); }
@Test public void testFetchAsync() throws Exception { // Make mock response and client JSONObject mockResponse = new JSONObject(); String createAtStr = "2015-08-09T22:15:13.460Z"; long createAtLong = ParseDateFormat.getInstance().parse(createAtStr).getTime(); String updateAtStr = "2015-08-09T22:15:13.497Z"; long updateAtLong = ParseDateFormat.getInstance().parse(updateAtStr).getTime(); mockResponse.put("createdAt", createAtStr); mockResponse.put("objectId", "testObjectId"); mockResponse.put("key", "value"); mockResponse.put("updatedAt", updateAtStr); ParseHttpClient restClient = ParseTestUtils.mockParseHttpClientWithResponse(mockResponse, 200, "OK"); // Make test state ParseObject.State state = new ParseObject.State.Builder("Test") .objectId("testObjectId") .build(); NetworkObjectController controller = new NetworkObjectController(restClient); ParseObject.State newState = ParseTaskUtils.wait(controller.fetchAsync(state, "sessionToken", ParseDecoder.get())); assertEquals(createAtLong, newState.createdAt()); assertEquals(updateAtLong, newState.updatedAt()); assertEquals("value", newState.get("key")); assertEquals("testObjectId", newState.objectId()); assertTrue(newState.isComplete()); }
@Test public void testFromJSONPayload() throws JSONException { JSONObject json = new JSONObject( "{" + "\"className\":\"GameScore\"," + "\"createdAt\":\"2015-06-22T21:23:41.733Z\"," + "\"objectId\":\"TT1ZskATqS\"," + "\"updatedAt\":\"2015-06-22T22:06:18.104Z\"," + "\"score\":{" + "\"__op\":\"Increment\"," + "\"amount\":1" + "}," + "\"age\":33" + "}"); ParseObject parseObject = ParseObject.fromJSONPayload(json, ParseDecoder.get()); assertEquals("GameScore", parseObject.getClassName()); assertEquals("TT1ZskATqS", parseObject.getObjectId()); ParseDateFormat format = ParseDateFormat.getInstance(); assertTrue(parseObject.getCreatedAt().equals(format.parse("2015-06-22T21:23:41.733Z"))); assertTrue(parseObject.getUpdatedAt().equals(format.parse("2015-06-22T22:06:18.104Z"))); Set<String> keys = parseObject.getState().keySet(); assertEquals(0, keys.size()); ParseOperationSet currentOperations = parseObject.operationSetQueue.getLast(); assertEquals(2, currentOperations.size()); }
@Test public void testFailingDelete() throws Exception { ParseRESTCommand.server = new URL("https://api.parse.com/1"); Parse.Configuration configuration = new Parse.Configuration.Builder(RuntimeEnvironment.application) .build(); ParsePlugins plugins = mock(ParsePlugins.class); when(plugins.configuration()).thenReturn(configuration); when(plugins.applicationContext()).thenReturn(RuntimeEnvironment.application); ParsePlugins.set(plugins); JSONObject mockResponse = new JSONObject(); mockResponse.put("code", 141); mockResponse.put("error", "Delete is not allowed"); ParseHttpClient restClient = ParseTestUtils.mockParseHttpClientWithResponse(mockResponse, 400, "Bad Request"); when(plugins.restClient()).thenReturn(restClient); ParseObject.State state = mock(ParseObject.State.class); when(state.className()).thenReturn("TestObject"); when(state.objectId()).thenReturn("test_id"); when(state.keySet()).thenReturn(Collections.singleton("key")); when(state.get("key")).thenReturn("data"); ParseObject object = ParseObject.from(state); thrown.expect(ParseException.class); thrown.expectMessage("Delete is not allowed"); object.delete(); }
@Test public void testParcelable() { long updatedAt = System.currentTimeMillis(); long createdAt = updatedAt + 10; ParseObject.State state = new ParseObject.State.Builder("TestObject") .objectId("fake") .createdAt(new Date(createdAt)) .updatedAt(new Date(updatedAt)) .isComplete(true) .put("foo", "bar") .put("baz", "qux") .availableKeys(Arrays.asList("safe", "keys")) .build(); Parcel parcel = Parcel.obtain(); state.writeToParcel(parcel, ParseParcelEncoder.get()); parcel.setDataPosition(0); ParseObject.State copy = ParseObject.State.createFromParcel(parcel, ParseParcelDecoder.get()); assertEquals(state.className(), copy.className()); assertEquals(state.objectId(), copy.objectId()); assertEquals(state.createdAt(), copy.createdAt()); assertEquals(state.updatedAt(), copy.updatedAt()); assertEquals(state.isComplete(), copy.isComplete()); assertEquals(state.keySet().size(), copy.keySet().size()); assertEquals(state.get("foo"), copy.get("foo")); assertEquals(state.get("baz"), copy.get("baz")); assertEquals(state.availableKeys().size(), copy.availableKeys().size()); assertTrue(state.availableKeys().containsAll(copy.availableKeys())); assertTrue(copy.availableKeys().containsAll(state.availableKeys())); }