embulk-input-dynamodb 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/master.yml +34 -0
  3. data/.github/workflows/test.yml +30 -0
  4. data/.scalafmt.conf +5 -0
  5. data/CHANGELOG.md +49 -0
  6. data/README.md +204 -54
  7. data/build.gradle +53 -44
  8. data/example/config-deprecated.yml +20 -0
  9. data/example/config-query-as-json.yml +18 -0
  10. data/example/config-query.yml +22 -0
  11. data/example/config-scan.yml +18 -0
  12. data/example/prepare_dynamodb_table.sh +67 -0
  13. data/gradle/wrapper/gradle-wrapper.jar +0 -0
  14. data/gradle/wrapper/gradle-wrapper.properties +1 -2
  15. data/gradlew +67 -48
  16. data/gradlew.bat +20 -10
  17. data/{test/run_dynamodb_local.sh → run_dynamodb_local.sh} +2 -1
  18. data/settings.gradle +1 -0
  19. data/src/main/scala/org/embulk/input/dynamodb/DeprecatedDynamodbInputPlugin.scala +73 -0
  20. data/src/main/scala/org/embulk/input/dynamodb/DynamodbInputPlugin.scala +76 -25
  21. data/src/main/scala/org/embulk/input/dynamodb/PluginTask.scala +132 -32
  22. data/src/main/scala/org/embulk/input/dynamodb/aws/Aws.scala +44 -0
  23. data/src/main/scala/org/embulk/input/dynamodb/aws/AwsClientConfiguration.scala +37 -0
  24. data/src/main/scala/org/embulk/input/dynamodb/aws/AwsCredentials.scala +240 -0
  25. data/src/main/scala/org/embulk/input/dynamodb/aws/AwsDynamodbConfiguration.scala +35 -0
  26. data/src/main/scala/org/embulk/input/dynamodb/aws/AwsEndpointConfiguration.scala +79 -0
  27. data/src/main/scala/org/embulk/input/dynamodb/aws/HttpProxy.scala +61 -0
  28. data/src/main/scala/org/embulk/input/dynamodb/deprecated/AttributeValueHelper.scala +72 -0
  29. data/src/main/scala/org/embulk/input/dynamodb/{Filter.scala → deprecated/Filter.scala} +3 -3
  30. data/src/main/scala/org/embulk/input/dynamodb/{FilterConfig.scala → deprecated/FilterConfig.scala} +13 -13
  31. data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/AbstractOperation.scala +36 -18
  32. data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/QueryOperation.scala +21 -13
  33. data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/ScanOperation.scala +20 -13
  34. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValue.scala +154 -0
  35. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValueEmbulkTypeTransformable.scala +245 -0
  36. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValueType.scala +33 -0
  37. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemColumnVisitor.scala +50 -0
  38. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemConsumer.scala +40 -0
  39. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemIterator.scala +19 -0
  40. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemReader.scala +64 -0
  41. data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemSchema.scala +135 -0
  42. data/src/main/scala/org/embulk/input/dynamodb/operation/AbstractDynamodbOperation.scala +169 -0
  43. data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbOperationProxy.scala +59 -0
  44. data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbQueryOperation.scala +72 -0
  45. data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbScanOperation.scala +93 -0
  46. data/src/main/scala/org/embulk/input/dynamodb/operation/EmbulkDynamodbOperation.scala +15 -0
  47. data/src/main/scala/org/embulk/input/dynamodb/package.scala +4 -9
  48. data/src/test/scala/org/embulk/input/dynamodb/AttributeValueHelperTest.scala +245 -101
  49. data/src/test/scala/org/embulk/input/dynamodb/AwsCredentialsTest.scala +150 -97
  50. data/src/test/scala/org/embulk/input/dynamodb/DynamodbQueryOperationTest.scala +188 -0
  51. data/src/test/scala/org/embulk/input/dynamodb/DynamodbScanOperationTest.scala +181 -0
  52. data/src/test/scala/org/embulk/input/dynamodb/testutil/EmbulkTestBase.scala +85 -0
  53. metadata +73 -49
  54. data/circle.yml +0 -16
  55. data/config/checkstyle/checkstyle.xml +0 -128
  56. data/config/checkstyle/default.xml +0 -108
  57. data/src/main/scala/org/embulk/input/dynamodb/AttributeValueHelper.scala +0 -41
  58. data/src/main/scala/org/embulk/input/dynamodb/AwsCredentials.scala +0 -63
  59. data/src/main/scala/org/embulk/input/dynamodb/DynamoDBClient.scala +0 -23
  60. data/src/test/resources/yaml/authMethodBasic.yml +0 -21
  61. data/src/test/resources/yaml/authMethodBasic_Error.yml +0 -19
  62. data/src/test/resources/yaml/authMethodEnv.yml +0 -19
  63. data/src/test/resources/yaml/authMethodProfile.yml +0 -20
  64. data/src/test/resources/yaml/dynamodb-local-query.yml +0 -25
  65. data/src/test/resources/yaml/dynamodb-local-scan.yml +0 -23
  66. data/src/test/resources/yaml/notSetAuthMethod.yml +0 -20
  67. data/src/test/scala/org/embulk/input/dynamodb/ope/QueryOperationTest.scala +0 -83
  68. data/src/test/scala/org/embulk/input/dynamodb/ope/ScanOperationTest.scala +0 -83
  69. data/test/create_table.sh +0 -16
  70. data/test/put_items.sh +0 -25
@@ -0,0 +1,59 @@
1
+ package org.embulk.input.dynamodb.operation
2
+
3
+ import java.util.Optional
4
+
5
+ import com.amazonaws.services.dynamodbv2.model.AttributeValue
6
+ import com.amazonaws.services.dynamodbv2.AmazonDynamoDB
7
+ import org.embulk.config.{
8
+ Config,
9
+ ConfigDefault,
10
+ ConfigException,
11
+ Task => EmbulkTask
12
+ }
13
+
14
+ object DynamodbOperationProxy {
15
+
16
+ trait Task extends EmbulkTask {
17
+
18
+ @Config("scan")
19
+ @ConfigDefault("null")
20
+ def getScan: Optional[DynamodbScanOperation.Task]
21
+
22
+ @Config("query")
23
+ @ConfigDefault("null")
24
+ def getQuery: Optional[DynamodbQueryOperation.Task]
25
+
26
+ @Config("table")
27
+ def getTable: String
28
+ }
29
+
30
+ def apply(task: Task): DynamodbOperationProxy = {
31
+ if (task.getScan.isPresent && task.getQuery.isPresent)
32
+ throw new ConfigException("You can use either \"scan\" or \"query\".")
33
+ if (!task.getScan.isPresent && !task.getQuery.isPresent)
34
+ throw new ConfigException("You must set either \"scan\" or \"query\".")
35
+ task.getScan.ifPresent(_.setTableName(task.getTable))
36
+ task.getQuery.ifPresent(_.setTableName(task.getTable))
37
+ new DynamodbOperationProxy(task)
38
+ }
39
+ }
40
+
41
+ case class DynamodbOperationProxy(task: DynamodbOperationProxy.Task)
42
+ extends EmbulkDynamodbOperation {
43
+
44
+ private def getOperation: EmbulkDynamodbOperation = {
45
+ task.getScan.ifPresent(t => return DynamodbScanOperation(t))
46
+ task.getQuery.ifPresent(t => return DynamodbQueryOperation(t))
47
+ throw new IllegalStateException()
48
+ }
49
+
50
+ private val operation: EmbulkDynamodbOperation = getOperation
51
+
52
+ override def getEmbulkTaskCount: Int = operation.getEmbulkTaskCount
53
+
54
+ override def run(
55
+ dynamodb: AmazonDynamoDB,
56
+ embulkTaskIndex: Int,
57
+ f: Seq[Map[String, AttributeValue]] => Unit
58
+ ): Unit = operation.run(dynamodb, embulkTaskIndex, f)
59
+ }
@@ -0,0 +1,72 @@
1
+ package org.embulk.input.dynamodb.operation
2
+
3
+ import com.amazonaws.services.dynamodbv2.model.{AttributeValue, QueryRequest}
4
+ import com.amazonaws.services.dynamodbv2.AmazonDynamoDB
5
+ import org.embulk.config.{Config, ConfigDefault}
6
+ import org.embulk.input.dynamodb.logger
7
+
8
+ import scala.jdk.CollectionConverters._
9
+ import scala.util.chaining._
10
+
11
+ object DynamodbQueryOperation {
12
+
13
+ trait Task extends AbstractDynamodbOperation.Task {
14
+
15
+ // ref. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions
16
+ @Config("key_condition_expression")
17
+ def getKeyConditionExpression: String
18
+
19
+ // TODO: Is it needed in the embulk context?
20
+ // ref. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions
21
+ @Config("scan_index_forward")
22
+ @ConfigDefault("true")
23
+ def getScanIndexForward: Boolean
24
+
25
+ }
26
+ }
27
+
28
+ case class DynamodbQueryOperation(task: DynamodbQueryOperation.Task)
29
+ extends AbstractDynamodbOperation(task) {
30
+
31
+ private def newRequest(
32
+ lastEvaluatedKey: Option[Map[String, AttributeValue]]
33
+ ): QueryRequest = {
34
+ new QueryRequest()
35
+ .tap(configureRequest(_, lastEvaluatedKey))
36
+ .tap(r => r.setKeyConditionExpression(task.getKeyConditionExpression))
37
+ .tap(r => r.setScanIndexForward(task.getScanIndexForward))
38
+ }
39
+
40
+ private def runInternal(
41
+ dynamodb: AmazonDynamoDB,
42
+ f: Seq[Map[String, AttributeValue]] => Unit,
43
+ lastEvaluatedKey: Option[Map[String, AttributeValue]] = None,
44
+ loadedRecords: Long = 0
45
+ ): Unit = {
46
+ val loadableRecords: Option[Long] = calculateLoadableRecords(loadedRecords)
47
+
48
+ val result = dynamodb.query(newRequest(lastEvaluatedKey).tap { req =>
49
+ logger.info(s"Call DynamodbQueryRequest: ${req.toString}")
50
+ })
51
+ loadableRecords match {
52
+ case Some(v) if (result.getCount > v) =>
53
+ f(result.getItems.asScala.take(v.toInt).map(_.asScala.toMap).toSeq)
54
+ case None =>
55
+ f(result.getItems.asScala.map(_.asScala.toMap).toSeq)
56
+ Option(result.getLastEvaluatedKey).foreach { lastEvaluatedKey =>
57
+ runInternal(
58
+ dynamodb,
59
+ f,
60
+ lastEvaluatedKey = Option(lastEvaluatedKey.asScala.toMap),
61
+ loadedRecords = loadedRecords + result.getCount
62
+ )
63
+ }
64
+ }
65
+ }
66
+
67
+ override def run(
68
+ dynamodb: AmazonDynamoDB,
69
+ embulkTaskIndex: Int,
70
+ f: Seq[Map[String, AttributeValue]] => Unit
71
+ ): Unit = runInternal(dynamodb, f)
72
+ }
@@ -0,0 +1,93 @@
1
+ package org.embulk.input.dynamodb.operation
2
+
3
+ import java.util.Optional
4
+
5
+ import com.amazonaws.services.dynamodbv2.model.{AttributeValue, ScanRequest}
6
+ import com.amazonaws.services.dynamodbv2.AmazonDynamoDB
7
+ import org.embulk.config.{Config, ConfigDefault, ConfigException}
8
+ import org.embulk.input.dynamodb.logger
9
+
10
+ import scala.jdk.CollectionConverters._
11
+ import scala.util.chaining._
12
+
13
+ object DynamodbScanOperation {
14
+
15
+ trait Task extends AbstractDynamodbOperation.Task {
16
+
17
+ // ref. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.ParallelScan
18
+ @Config("segment")
19
+ @ConfigDefault("null")
20
+ def getSegment: Optional[Int]
21
+
22
+ // ref. https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.ParallelScan
23
+ @Config("total_segment")
24
+ @ConfigDefault("null")
25
+ def getTotalSegment: Optional[Int]
26
+
27
+ }
28
+ }
29
+
30
+ case class DynamodbScanOperation(task: DynamodbScanOperation.Task)
31
+ extends AbstractDynamodbOperation(task) {
32
+
33
+ override def getEmbulkTaskCount: Int = {
34
+ if (task.getTotalSegment.isPresent && task.getSegment.isPresent) 1
35
+ else if (task.getTotalSegment.isPresent && !task.getSegment.isPresent)
36
+ task.getTotalSegment.get()
37
+ else if (!task.getTotalSegment.isPresent && !task.getSegment.isPresent) 1
38
+ else // if (!task.getTotalSegment.isPresent && task.getSegment.isPresent)
39
+ throw new ConfigException(
40
+ "\"segment\" option must be set with \"total_segment\" option."
41
+ )
42
+ }
43
+
44
+ private def newRequest(
45
+ embulkTaskIndex: Int,
46
+ lastEvaluatedKey: Option[Map[String, AttributeValue]]
47
+ ): ScanRequest = {
48
+ new ScanRequest()
49
+ .tap(configureRequest(_, lastEvaluatedKey))
50
+ .tap { r =>
51
+ task.getTotalSegment.ifPresent { totalSegment =>
52
+ r.setTotalSegments(totalSegment)
53
+ r.setSegment(task.getSegment.orElse(embulkTaskIndex))
54
+ }
55
+ }
56
+ }
57
+
58
+ private def runInternal(
59
+ dynamodb: AmazonDynamoDB,
60
+ embulkTaskIndex: Int,
61
+ f: Seq[Map[String, AttributeValue]] => Unit,
62
+ lastEvaluatedKey: Option[Map[String, AttributeValue]] = None,
63
+ loadedRecords: Long = 0
64
+ ): Unit = {
65
+ val loadableRecords: Option[Long] = calculateLoadableRecords(loadedRecords)
66
+
67
+ val result =
68
+ dynamodb.scan(newRequest(embulkTaskIndex, lastEvaluatedKey).tap { req =>
69
+ logger.info(s"Call DynamodbQueryRequest: ${req.toString}")
70
+ })
71
+ loadableRecords match {
72
+ case Some(v) if (result.getCount > v) =>
73
+ f(result.getItems.asScala.take(v.toInt).map(_.asScala.toMap).toSeq)
74
+ case None =>
75
+ f(result.getItems.asScala.map(_.asScala.toMap).toSeq)
76
+ Option(result.getLastEvaluatedKey).foreach { lastEvaluatedKey =>
77
+ runInternal(
78
+ dynamodb,
79
+ embulkTaskIndex,
80
+ f,
81
+ lastEvaluatedKey = Option(lastEvaluatedKey.asScala.toMap),
82
+ loadedRecords = loadedRecords + result.getCount
83
+ )
84
+ }
85
+ }
86
+ }
87
+
88
+ override def run(
89
+ dynamodb: AmazonDynamoDB,
90
+ embulkTaskIndex: Int,
91
+ f: Seq[Map[String, AttributeValue]] => Unit
92
+ ): Unit = runInternal(dynamodb, embulkTaskIndex, f)
93
+ }
@@ -0,0 +1,15 @@
1
+ package org.embulk.input.dynamodb.operation
2
+
3
+ import com.amazonaws.services.dynamodbv2.AmazonDynamoDB
4
+ import com.amazonaws.services.dynamodbv2.model.AttributeValue
5
+
6
+ trait EmbulkDynamodbOperation {
7
+
8
+ def getEmbulkTaskCount: Int = 1
9
+
10
+ def run(
11
+ dynamodb: AmazonDynamoDB,
12
+ embulkTaskIndex: Int,
13
+ f: Seq[Map[String, AttributeValue]] => Unit
14
+ ): Unit
15
+ }
@@ -1,14 +1,9 @@
1
1
  package org.embulk.input
2
2
 
3
- import com.google.common.base.Optional
4
- import org.embulk.config.ConfigException
3
+ import org.slf4j.{Logger, LoggerFactory}
5
4
 
6
5
  package object dynamodb {
7
- def require[A](value: Optional[A], message: String): A = {
8
- if (value.isPresent) {
9
- value.get()
10
- } else {
11
- throw new ConfigException("Required option is not set: " + message)
12
- }
13
- }
6
+
7
+ val logger: Logger = LoggerFactory.getLogger(classOf[DynamodbInputPlugin])
8
+
14
9
  }
@@ -1,20 +1,21 @@
1
1
  package org.embulk.input.dynamodb
2
2
 
3
-
4
3
  import java.io.File
5
4
  import java.{util => JUtil}
6
5
 
7
6
  import com.amazonaws.services.dynamodbv2.model.AttributeValue
8
7
  import com.fasterxml.jackson.databind.ObjectMapper
9
- import org.embulk.input.dynamodb.AttributeValueHelper._
8
+ import org.embulk.input.dynamodb.deprecated.AttributeValueHelper._
10
9
  import org.hamcrest.CoreMatchers._
10
+ import org.hamcrest.MatcherAssert.assertThat
11
11
  import org.junit.Assert._
12
12
  import org.junit.Test
13
13
  import org.msgpack.value.ValueFactory
14
14
 
15
- import scala.collection.JavaConverters._
15
+ import scala.jdk.CollectionConverters._
16
16
 
17
17
  class AttributeValueHelperTest {
18
+
18
19
  @Test
19
20
  def decodeTest(): Unit = {
20
21
  val stringValue = decodeToValue(new AttributeValue().withS("STR"))
@@ -23,7 +24,9 @@ class AttributeValueHelperTest {
23
24
  val intValue = decodeToValue(new AttributeValue().withN("123456789"))
24
25
  assertEquals(intValue.asNumberValue().toInt, 123456789)
25
26
 
26
- val doubleValue = decodeToValue(new AttributeValue().withN("-98765432.00000001"))
27
+ val doubleValue = decodeToValue(
28
+ new AttributeValue().withN("-98765432.00000001")
29
+ )
27
30
  assertEquals(doubleValue.asNumberValue().toDouble, -98765432.00000001, 0.0)
28
31
 
29
32
  val trueValue = decodeToValue(new AttributeValue().withBOOL(true))
@@ -36,162 +39,303 @@ class AttributeValueHelperTest {
36
39
  assertEquals(nilValue.isNilValue, true)
37
40
  }
38
41
 
39
-
40
42
  @Test
41
43
  def listDecodeTest(): Unit = {
42
- val stringListValue = decodeToValue(new AttributeValue().withL(
43
- new AttributeValue().withS("ValueA"),
44
- new AttributeValue().withS("ValueB"),
45
- new AttributeValue().withS("ValueC")))
44
+ val stringListValue = decodeToValue(
45
+ new AttributeValue().withL(
46
+ new AttributeValue().withS("ValueA"),
47
+ new AttributeValue().withS("ValueB"),
48
+ new AttributeValue().withS("ValueC")
49
+ )
50
+ )
46
51
 
47
52
  assertTrue(stringListValue.isArrayValue)
48
53
  assertEquals(stringListValue.asArrayValue().size(), 3)
49
54
 
50
55
  assertTrue(stringListValue.asArrayValue().get(0).isStringValue)
51
- assertEquals(stringListValue.asArrayValue().get(0).asStringValue().asString(), "ValueA")
52
- assertEquals(stringListValue.asArrayValue().get(1).asStringValue().asString(), "ValueB")
53
- assertEquals(stringListValue.asArrayValue().get(2).asStringValue().asString(), "ValueC")
54
-
55
-
56
- val numberListValue = decodeToValue(new AttributeValue().withL(
57
- new AttributeValue().withN("123"),
58
- new AttributeValue().withN("-456"),
59
- new AttributeValue().withN("0.0000045679"),
60
- new AttributeValue().withN("-1234567890.123")))
56
+ assertEquals(
57
+ stringListValue.asArrayValue().get(0).asStringValue().asString(),
58
+ "ValueA"
59
+ )
60
+ assertEquals(
61
+ stringListValue.asArrayValue().get(1).asStringValue().asString(),
62
+ "ValueB"
63
+ )
64
+ assertEquals(
65
+ stringListValue.asArrayValue().get(2).asStringValue().asString(),
66
+ "ValueC"
67
+ )
68
+
69
+ val numberListValue = decodeToValue(
70
+ new AttributeValue().withL(
71
+ new AttributeValue().withN("123"),
72
+ new AttributeValue().withN("-456"),
73
+ new AttributeValue().withN("0.0000045679"),
74
+ new AttributeValue().withN("-1234567890.123")
75
+ )
76
+ )
61
77
 
62
78
  assertTrue(numberListValue.isArrayValue)
63
79
  assertEquals(numberListValue.asArrayValue().size(), 4)
64
80
 
65
81
  assertTrue(numberListValue.asArrayValue().get(0).isIntegerValue)
66
- assertEquals(numberListValue.asArrayValue().get(0).asNumberValue().toInt, 123)
67
- assertEquals(numberListValue.asArrayValue().get(1).asNumberValue().toInt, -456)
82
+ assertEquals(
83
+ numberListValue.asArrayValue().get(0).asNumberValue().toInt,
84
+ 123
85
+ )
86
+ assertEquals(
87
+ numberListValue.asArrayValue().get(1).asNumberValue().toInt,
88
+ -456
89
+ )
68
90
 
69
91
  assertTrue(numberListValue.asArrayValue().get(2).isFloatValue)
70
- assertEquals(numberListValue.asArrayValue().get(2).asNumberValue().toDouble, 0.0000045679, 0.0)
71
- assertEquals(numberListValue.asArrayValue().get(3).asNumberValue().toDouble, -1234567890.123, 0.0)
72
-
73
-
74
- val stringSetValue = decodeToValue(new AttributeValue().withSS(
75
- new JUtil.HashSet[String]() {
92
+ assertEquals(
93
+ numberListValue.asArrayValue().get(2).asNumberValue().toDouble,
94
+ 0.0000045679,
95
+ 0.0
96
+ )
97
+ assertEquals(
98
+ numberListValue.asArrayValue().get(3).asNumberValue().toDouble,
99
+ -1234567890.123,
100
+ 0.0
101
+ )
102
+
103
+ val stringSetValue = decodeToValue(
104
+ new AttributeValue().withSS(new JUtil.HashSet[String]() {
76
105
  add("ValueA")
77
106
  add("ValueB")
78
107
  add("ValueC")
79
- }))
108
+ })
109
+ )
80
110
 
81
111
  assertTrue(stringSetValue.isArrayValue)
82
112
  assertEquals(stringSetValue.asArrayValue().size(), 3)
83
113
 
84
- assertThat(List("ValueA", "ValueB", "ValueC").asJava,
114
+ assertThat(
115
+ List("ValueA", "ValueB", "ValueC").asJava,
85
116
  hasItems(
86
117
  equalTo(stringSetValue.asArrayValue().get(0).asStringValue().asString),
87
118
  equalTo(stringSetValue.asArrayValue().get(1).asStringValue().asString),
88
- equalTo(stringSetValue.asArrayValue().get(2).asStringValue().asString)))
89
-
119
+ equalTo(stringSetValue.asArrayValue().get(2).asStringValue().asString)
120
+ )
121
+ )
90
122
 
91
- val numberSetValue = decodeToValue(new AttributeValue().withNS(
92
- new JUtil.HashSet[String]() {
123
+ val numberSetValue = decodeToValue(
124
+ new AttributeValue().withNS(new JUtil.HashSet[String]() {
93
125
  add("123")
94
126
  add("-456")
95
127
  add("0.0000045679")
96
128
  add("-1234567890.123")
97
- }))
129
+ })
130
+ )
98
131
 
99
132
  assertTrue(numberSetValue.isArrayValue)
100
133
  assertEquals(numberSetValue.asArrayValue().size(), 4)
101
134
  }
102
135
 
103
-
104
136
  @Test
105
137
  def mapDecodeTest(): Unit = {
106
- val stringMap = decodeToValue(new AttributeValue().withM(
107
- new JUtil.HashMap[String, AttributeValue]() {
138
+ val stringMap = decodeToValue(
139
+ new AttributeValue().withM(new JUtil.HashMap[String, AttributeValue]() {
108
140
  put("KeyA", new AttributeValue().withS("ValueA"))
109
141
  put("KeyB", new AttributeValue().withS("ValueB"))
110
142
  put("KeyC", new AttributeValue().withS("ValueC"))
111
- }))
143
+ })
144
+ )
112
145
 
113
146
  assertTrue(stringMap.isMapValue)
114
147
  assertEquals(stringMap.asMapValue().size(), 3)
115
- assertEquals(stringMap.asMapValue().map().get(ValueFactory.newString("KeyA")).asStringValue().asString(), "ValueA")
116
- assertEquals(stringMap.asMapValue().map().get(ValueFactory.newString("KeyB")).asStringValue().asString(), "ValueB")
117
- assertEquals(stringMap.asMapValue().map().get(ValueFactory.newString("KeyC")).asStringValue().asString(), "ValueC")
118
-
119
-
120
- val numberMap = decodeToValue(new AttributeValue().withM(
121
- new JUtil.HashMap[String, AttributeValue]() {
148
+ assertEquals(
149
+ stringMap
150
+ .asMapValue()
151
+ .map()
152
+ .get(ValueFactory.newString("KeyA"))
153
+ .asStringValue()
154
+ .asString(),
155
+ "ValueA"
156
+ )
157
+ assertEquals(
158
+ stringMap
159
+ .asMapValue()
160
+ .map()
161
+ .get(ValueFactory.newString("KeyB"))
162
+ .asStringValue()
163
+ .asString(),
164
+ "ValueB"
165
+ )
166
+ assertEquals(
167
+ stringMap
168
+ .asMapValue()
169
+ .map()
170
+ .get(ValueFactory.newString("KeyC"))
171
+ .asStringValue()
172
+ .asString(),
173
+ "ValueC"
174
+ )
175
+
176
+ val numberMap = decodeToValue(
177
+ new AttributeValue().withM(new JUtil.HashMap[String, AttributeValue]() {
122
178
  put("KeyA", new AttributeValue().withN("123"))
123
179
  put("KeyB", new AttributeValue().withN("-456"))
124
180
  put("KeyC", new AttributeValue().withN("0.0000045679"))
125
181
  put("KeyD", new AttributeValue().withN("-1234567890.123"))
126
- }))
182
+ })
183
+ )
127
184
 
128
185
  assertTrue(numberMap.isMapValue)
129
186
  assertEquals(numberMap.asMapValue().size(), 4)
130
187
 
131
- assertTrue(numberMap.asMapValue().map().get(ValueFactory.newString("KeyA")).isIntegerValue)
132
- assertEquals(numberMap.asMapValue().map().get(ValueFactory.newString("KeyA")).asNumberValue().toInt, 123)
133
- assertEquals(numberMap.asMapValue().map().get(ValueFactory.newString("KeyB")).asNumberValue().toInt, -456)
134
-
135
- assertTrue(numberMap.asMapValue().map().get(ValueFactory.newString("KeyC")).isFloatValue)
136
- assertEquals(numberMap.asMapValue().map().get(ValueFactory.newString("KeyC")).asFloatValue().toDouble, 0.0000045679, 0.0)
137
- assertEquals(numberMap.asMapValue().map().get(ValueFactory.newString("KeyD")).asFloatValue().toDouble, -1234567890.123, 0.0)
188
+ assertTrue(
189
+ numberMap
190
+ .asMapValue()
191
+ .map()
192
+ .get(ValueFactory.newString("KeyA"))
193
+ .isIntegerValue
194
+ )
195
+ assertEquals(
196
+ numberMap
197
+ .asMapValue()
198
+ .map()
199
+ .get(ValueFactory.newString("KeyA"))
200
+ .asNumberValue()
201
+ .toInt,
202
+ 123
203
+ )
204
+ assertEquals(
205
+ numberMap
206
+ .asMapValue()
207
+ .map()
208
+ .get(ValueFactory.newString("KeyB"))
209
+ .asNumberValue()
210
+ .toInt,
211
+ -456
212
+ )
213
+
214
+ assertTrue(
215
+ numberMap
216
+ .asMapValue()
217
+ .map()
218
+ .get(ValueFactory.newString("KeyC"))
219
+ .isFloatValue
220
+ )
221
+ assertEquals(
222
+ numberMap
223
+ .asMapValue()
224
+ .map()
225
+ .get(ValueFactory.newString("KeyC"))
226
+ .asFloatValue()
227
+ .toDouble,
228
+ 0.0000045679,
229
+ 0.0
230
+ )
231
+ assertEquals(
232
+ numberMap
233
+ .asMapValue()
234
+ .map()
235
+ .get(ValueFactory.newString("KeyD"))
236
+ .asFloatValue()
237
+ .toDouble,
238
+ -1234567890.123,
239
+ 0.0
240
+ )
138
241
  }
139
242
 
140
- def attr[A](value: A)(implicit f: A=> AttributeValue): AttributeValue = f(value)
141
- implicit def StringAttributeValue(value: String): AttributeValue
142
- = new AttributeValue().withS(value)
143
- implicit def IntegerAttributeValue(value: Int): AttributeValue
144
- = new AttributeValue().withN(value.toString)
145
- implicit def LongAttributeValue(value: Long): AttributeValue
146
- = new AttributeValue().withN(value.toString)
147
- implicit def FloatAttributeValue(value: Float): AttributeValue
148
- = new AttributeValue().withN(value.toString)
149
- implicit def DoubleAttributeValue(value: Double): AttributeValue
150
- = new AttributeValue().withN(value.toString)
151
- implicit def BooleanAttributeValue(value: Boolean): AttributeValue
152
- = new AttributeValue().withBOOL(value)
153
- implicit def MapAttributeValue(value: Map[String, AttributeValue]): AttributeValue
154
- = new AttributeValue().withM(value.asJava)
155
- implicit def ListAttributeValue(value: List[AttributeValue]): AttributeValue
156
- = new AttributeValue().withL(value.asJava)
243
+ def attr[A](value: A)(implicit f: A => AttributeValue): AttributeValue =
244
+ f(value)
245
+
246
+ implicit def StringAttributeValue(value: String): AttributeValue =
247
+ new AttributeValue().withS(value)
248
+
249
+ implicit def IntegerAttributeValue(value: Int): AttributeValue =
250
+ new AttributeValue().withN(value.toString)
251
+
252
+ implicit def LongAttributeValue(value: Long): AttributeValue =
253
+ new AttributeValue().withN(value.toString)
254
+
255
+ implicit def FloatAttributeValue(value: Float): AttributeValue =
256
+ new AttributeValue().withN(value.toString)
257
+
258
+ implicit def DoubleAttributeValue(value: Double): AttributeValue =
259
+ new AttributeValue().withN(value.toString)
260
+
261
+ implicit def BooleanAttributeValue(value: Boolean): AttributeValue =
262
+ new AttributeValue().withBOOL(value)
263
+
264
+ implicit def MapAttributeValue(
265
+ value: Map[String, AttributeValue]
266
+ ): AttributeValue = new AttributeValue().withM(value.asJava)
267
+
268
+ implicit def ListAttributeValue(value: List[AttributeValue]): AttributeValue =
269
+ new AttributeValue().withL(value.asJava)
157
270
 
158
271
  @Test
159
272
  def nestedDecodeTest(): Unit = {
160
273
  // TODO: Json -> AttributeValue...
161
- val testData = decodeToValue(attr(Map(
162
- "_id" -> attr("56d8e1377a72374918f73bd2"),
163
- "index" -> attr(0),
164
- "guid" -> attr("5309640c-499a-43f6-801d-3076c810892b"),
165
- "isActive" -> attr(true),
166
- "age" -> attr(37),
167
- "name" -> attr("Battle Lancaster"),
168
- "email" -> attr("battlelancaster@zytrac.com"),
169
- "registered" -> attr("2014-07-16T04:40:58 -09:00"),
170
- "latitude" -> attr(45.574906),
171
- "longitude" -> attr(36.596302),
172
- "tags" -> attr(List(
173
- attr("veniam"),
174
- attr("exercitation"),
175
- attr("velit"),
176
- attr("pariatur"),
177
- attr("sit"),
178
- attr("non"),
179
- attr("dolore"))),
180
- "friends" -> attr(List(
181
- attr(Map("id" -> attr(0), "name" -> attr("Mejia Montgomery"),
182
- "tags" -> attr(List(attr("duis"), attr("proident"), attr("et"))))),
183
- attr(Map("id" -> attr(1), "name" -> attr("Carpenter Reed"),
184
- "tags" -> attr(List(attr("labore"), attr("nisi"), attr("ipsum"))))),
185
- attr(Map("id" -> attr(2), "name" -> attr("Gamble Watts"),
186
- "tags" -> attr(List(attr("occaecat"), attr("voluptate"), attr("eu")))))
187
- ))
274
+ val testData = decodeToValue(
275
+ attr(
276
+ Map(
277
+ "_id" -> attr("56d8e1377a72374918f73bd2"),
278
+ "index" -> attr(0),
279
+ "guid" -> attr("5309640c-499a-43f6-801d-3076c810892b"),
280
+ "isActive" -> attr(true),
281
+ "age" -> attr(37),
282
+ "name" -> attr("Battle Lancaster"),
283
+ "email" -> attr("battlelancaster@zytrac.com"),
284
+ "registered" -> attr("2014-07-16T04:40:58 -09:00"),
285
+ "latitude" -> attr(45.574906),
286
+ "longitude" -> attr(36.596302),
287
+ "tags" -> attr(
288
+ List(
289
+ attr("veniam"),
290
+ attr("exercitation"),
291
+ attr("velit"),
292
+ attr("pariatur"),
293
+ attr("sit"),
294
+ attr("non"),
295
+ attr("dolore")
296
+ )
297
+ ),
298
+ "friends" -> attr(
299
+ List(
300
+ attr(
301
+ Map(
302
+ "id" -> attr(0),
303
+ "name" -> attr("Mejia Montgomery"),
304
+ "tags" -> attr(
305
+ List(attr("duis"), attr("proident"), attr("et"))
306
+ )
307
+ )
308
+ ),
309
+ attr(
310
+ Map(
311
+ "id" -> attr(1),
312
+ "name" -> attr("Carpenter Reed"),
313
+ "tags" -> attr(
314
+ List(attr("labore"), attr("nisi"), attr("ipsum"))
315
+ )
316
+ )
317
+ ),
318
+ attr(
319
+ Map(
320
+ "id" -> attr(2),
321
+ "name" -> attr("Gamble Watts"),
322
+ "tags" -> attr(
323
+ List(attr("occaecat"), attr("voluptate"), attr("eu"))
324
+ )
325
+ )
326
+ )
327
+ )
328
+ )
329
+ )
188
330
  )
189
- ))
331
+ )
190
332
 
191
- val testA = new ObjectMapper().readValue(
192
- testData.toJson, classOf[JUtil.Map[String, Any]])
333
+ val testA = new ObjectMapper()
334
+ .readValue(testData.toJson, classOf[JUtil.Map[String, Any]])
193
335
  val testB = new ObjectMapper().readValue(
194
- new File("src/test/resources/json/test.json"), classOf[JUtil.Map[String, Any]])
336
+ new File("src/test/resources/json/test.json"),
337
+ classOf[JUtil.Map[String, Any]]
338
+ )
195
339
 
196
340
  assertThat(testA, is(testB))
197
341
  }