Java tutorial
/* * Copyright (c) 2016, Alexander Patrikalakis (amcp@me.com) * Copyright (c) 2015, Daisuke Miyamoto (dai.0304@gmail.com) * * This software is dual-licensed under: * * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any * later version; * - the Apache Software License (ASL) version 2.0. * * The text of this file and of both licenses is available at the root of this * project or, if you have the jar distribution, in directory META-INF/, under * the names LGPL-3.0.txt and ASL-2.0.txt respectively. * * Direct link to the sources: * * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt */ package com.github.fge.jsonpatch; import java.math.BigDecimal; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.amazonaws.AmazonServiceException; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.document.Item; import com.amazonaws.services.dynamodbv2.document.PrimaryKey; import com.amazonaws.services.dynamodbv2.document.Table; import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome; import com.amazonaws.services.dynamodbv2.document.internal.InternalUtils; import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec; import com.amazonaws.services.dynamodbv2.local.embedded.DynamoDBEmbedded; import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; import com.amazonaws.services.dynamodbv2.model.KeyType; import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; import com.amazonaws.services.dynamodbv2.model.ReturnValue; import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; import com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder; import com.amazonaws.services.dynamodbv2.xspec.UpdateItemExpressionSpec; import com.fasterxml.jackson.databind.JsonNode; import com.github.fge.jackson.JsonLoader; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; public class JsonPatchToXSpecReplace { private static final String KEY_ATTRIBUTE_NAME = "key"; private static final String VALUE = "keyValue"; private static final PrimaryKey PK = new PrimaryKey(KEY_ATTRIBUTE_NAME, VALUE); private static final String TABLE_NAME = "json_patch_test"; private Table table; @BeforeTest public void setUp() throws Exception { AmazonDynamoDB amazonDynamoDB = DynamoDBEmbedded.create().amazonDynamoDB(); try { amazonDynamoDB.deleteTable(TABLE_NAME); } catch (ResourceNotFoundException e) { //do nothing because the first run will not have the table. } amazonDynamoDB.createTable(new CreateTableRequest().withTableName(TABLE_NAME) .withProvisionedThroughput(new ProvisionedThroughput(1L, 1L)) .withAttributeDefinitions(new AttributeDefinition().withAttributeName(KEY_ATTRIBUTE_NAME) .withAttributeType(ScalarAttributeType.S)) .withKeySchema( new KeySchemaElement().withAttributeName(KEY_ATTRIBUTE_NAME).withKeyType(KeyType.HASH))); table = new Table(amazonDynamoDB, TABLE_NAME); } @Test(expectedExceptions = ConditionalCheckFailedException.class) public void testReplaceSinglePathNumberNonextant() throws Exception { // setup table.putItem(Item.fromMap(ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE).build())); String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a\", \"value\": 1 } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); table.updateItem(KEY_ATTRIBUTE_NAME, VALUE, spec); // verify table.getItem(PK); //throw } @Test public void testReplaceSinglePathNumberExtant() throws Exception { // setup table.putItem(Item.fromMap(ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE) .put("a", "peekaboo").build())); String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a\", \"value\": 1 } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); UpdateItemOutcome out = table.updateItem(new UpdateItemSpec().withPrimaryKey(KEY_ATTRIBUTE_NAME, VALUE) .withExpressionSpec(spec).withReturnValues(ReturnValue.ALL_OLD)); Item oldItem = Item.fromMap(InternalUtils.toSimpleMapValue(out.getUpdateItemResult().getAttributes())); Assert.assertTrue(oldItem.hasAttribute("a")); Assert.assertEquals(oldItem.getString("a"), "peekaboo"); // verify Item item = table.getItem(PK); Assert.assertTrue(item.hasAttribute("key")); Assert.assertEquals(item.getString("key"), "keyValue"); Assert.assertTrue(item.hasAttribute("a")); Assert.assertEquals(item.getNumber("a").longValue(), 1L); } @Test(expectedExceptions = ConditionalCheckFailedException.class) public void testReplaceNestedPathString() throws Exception { // setup table.putItem(Item.fromMap(ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE) .put("a", ImmutableMap.of("a", 1L)).build())); String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a/b\", \"value\": \"foo\" } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); table.updateItem(KEY_ATTRIBUTE_NAME, VALUE, spec); } @Test public void test_replace_existingNestedPath_string() throws Exception { // setup table.putItem(Item.fromMap(ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE) .put("a", ImmutableMap.of("a", 2L, "b", true)).build())); String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a/b\", \"value\": \"bar\" } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); table.updateItem(KEY_ATTRIBUTE_NAME, VALUE, spec); // verify Item item = table.getItem(PK); Assert.assertTrue(item.hasAttribute("key")); Assert.assertEquals(item.getString("key"), "keyValue"); Assert.assertTrue(item.hasAttribute("a")); Assert.assertTrue(item.getRawMap("a").containsKey("a")); Assert.assertEquals(((BigDecimal) item.getRawMap("a").get("a")).longValue(), 2L); Assert.assertTrue(item.getRawMap("a").containsKey("b")); Assert.assertEquals(item.getRawMap("a").get("b"), "bar"); } @Test(expectedExceptions = AmazonServiceException.class) public void test_replace_property_toScalar_string() throws Exception { // setup table.putItem(Item.fromMap( ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE).put("a", 1L).build())); String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a/b\", \"value\": \"bar\" } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); table.updateItem(KEY_ATTRIBUTE_NAME, VALUE, spec); } @Test public void test_replace_singlePath_stringSet() throws Exception { // setup table.putItem(Item.fromMap( ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE).put("a", 1L).build())); String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a\", \"value\": [\"foo\",\"bar\"] } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); table.updateItem(KEY_ATTRIBUTE_NAME, VALUE, spec); // verify Item item = table.getItem(PK); Assert.assertTrue(item.hasAttribute("key")); Assert.assertEquals(item.getString("key"), "keyValue"); Assert.assertTrue(item.hasAttribute("a")); Assert.assertTrue(item.getList("a").contains("foo")); Assert.assertTrue(item.getList("a").contains("bar")); } @Test public void test_replace_replaceExisting_singlePath_stringSet() throws Exception { // setup table.putItem(Item.fromMap(ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE) .put("a", ImmutableSet.of("foo", "bar")).build())); String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a\", \"value\": [\"baz\",\"qux\"] } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); table.updateItem(KEY_ATTRIBUTE_NAME, VALUE, spec); // verify Item item = table.getItem(PK); Assert.assertTrue(item.hasAttribute("key")); Assert.assertEquals(item.getString("key"), "keyValue"); Assert.assertTrue(item.hasAttribute("a")); Assert.assertEquals(item.getList("a").size(), 2); Assert.assertTrue(item.getList("a").contains("baz")); Assert.assertTrue(item.getList("a").contains("qux")); } @Test public void test_replace_singlePath_object() throws Exception { table.putItem(Item.fromMap( ImmutableMap.<String, Object>builder().put(KEY_ATTRIBUTE_NAME, VALUE).put("a", 1L).build())); // setup String patchExpression = "[ { \"op\": \"replace\", \"path\": \"/a\", \"value\": {\"b\": \"c\", \"d\": 1} } ]"; JsonNode jsonNode = JsonLoader.fromString(patchExpression); JsonPatch jsonPatch = JsonPatch.fromJson(jsonNode); // exercise ExpressionSpecBuilder builder = jsonPatch.get(); UpdateItemExpressionSpec spec = builder.buildForUpdate(); table.updateItem(KEY_ATTRIBUTE_NAME, VALUE, spec); // verify Item item = table.getItem(PK); Assert.assertTrue(item.hasAttribute("key")); Assert.assertEquals(item.getString("key"), "keyValue"); Assert.assertTrue(item.hasAttribute("a")); Assert.assertTrue(item.getRawMap("a").containsKey("b")); Assert.assertEquals(item.getRawMap("a").get("b"), "c"); Assert.assertTrue(item.getRawMap("a").containsKey("d")); Assert.assertEquals(((BigDecimal) item.getRawMap("a").get("d")).longValue(), 1L); } }