embulk-output-kintone 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -0
  3. data/classpath/embulk-output-kintone-1.2.0.jar +0 -0
  4. data/classpath/{shadow-kintone-java-client-1.1.0-all.jar → shadow-kintone-java-client-1.2.0-all.jar} +0 -0
  5. data/src/main/java/org/embulk/output/kintone/KintoneClient.java +117 -0
  6. data/src/main/java/org/embulk/output/kintone/KintoneColumnType.java +30 -13
  7. data/src/main/java/org/embulk/output/kintone/KintoneColumnVisitor.java +54 -4
  8. data/src/main/java/org/embulk/output/kintone/KintoneMode.java +52 -4
  9. data/src/main/java/org/embulk/output/kintone/KintoneOutputPlugin.java +0 -17
  10. data/src/main/java/org/embulk/output/kintone/KintonePageOutput.java +106 -118
  11. data/src/main/java/org/embulk/output/kintone/PluginTask.java +5 -0
  12. data/src/main/java/org/embulk/output/kintone/record/Id.java +18 -0
  13. data/src/main/java/org/embulk/output/kintone/record/IdOrUpdateKey.java +45 -0
  14. data/src/main/java/org/embulk/output/kintone/record/Skip.java +14 -0
  15. data/src/main/java/org/embulk/output/kintone/util/Lazy.java +20 -0
  16. data/src/test/java/org/embulk/output/kintone/KintoneClientTest.java +139 -0
  17. data/src/test/java/org/embulk/output/kintone/KintoneColumnVisitorTest.java +33 -33
  18. data/src/test/java/org/embulk/output/kintone/KintoneColumnVisitorVerifier.java +6 -6
  19. data/src/test/java/org/embulk/output/kintone/KintonePageOutputVerifier.java +79 -53
  20. data/src/test/java/org/embulk/output/kintone/MockClient.java +112 -0
  21. data/src/test/java/org/embulk/output/kintone/TestKintoneOutputPlugin.java +64 -16
  22. data/src/test/java/org/embulk/output/kintone/TestTaskMode.java +1 -0
  23. data/src/test/java/org/embulk/output/kintone/TestTaskReduce.java +1 -0
  24. data/src/test/java/org/embulk/output/kintone/TestTaskReduceSubtable.java +1 -0
  25. data/src/test/java/org/embulk/output/kintone/TestTaskSkip.java +80 -0
  26. data/src/test/java/org/embulk/output/kintone/TestTaskSkipId.java +80 -0
  27. data/src/test/resources/org/embulk/output/kintone/client/config.yml +1 -0
  28. data/src/test/resources/org/embulk/output/kintone/task/config.yml +1 -0
  29. data/src/test/resources/org/embulk/output/kintone/task/mode/upsert_never_skip_double_single_line_text_add_values.json +1 -0
  30. data/src/test/resources/org/embulk/output/kintone/task/reduce/upsert_never_skip_double_single_line_text_add_values.json +1 -0
  31. data/src/test/resources/org/embulk/output/kintone/task/skip/config.yml +1 -0
  32. data/src/test/resources/org/embulk/output/kintone/task/skip/input.csv +7 -0
  33. data/src/test/resources/org/embulk/output/kintone/task/skip/insert_add_records.jsonl +6 -0
  34. data/src/test/resources/org/embulk/output/kintone/task/skip/insert_always_skip_add_records.jsonl +6 -0
  35. data/src/test/resources/org/embulk/output/kintone/task/skip/insert_always_skip_prefer_nulls_add_records.jsonl +6 -0
  36. data/src/test/resources/org/embulk/output/kintone/task/skip/insert_never_skip_add_records.jsonl +6 -0
  37. data/src/test/resources/org/embulk/output/kintone/task/skip/insert_never_skip_prefer_nulls_add_records.jsonl +6 -0
  38. data/src/test/resources/org/embulk/output/kintone/task/skip/insert_prefer_nulls_add_records.jsonl +6 -0
  39. data/src/test/resources/org/embulk/output/kintone/task/skip/update_always_skip_long_number_add_values.json +1 -0
  40. data/src/test/resources/org/embulk/output/kintone/task/skip/update_always_skip_long_number_values.json +1 -0
  41. data/src/test/resources/org/embulk/output/kintone/task/skip/update_always_skip_prefer_nulls_long_number_add_values.json +1 -0
  42. data/src/test/resources/org/embulk/output/kintone/task/skip/update_always_skip_prefer_nulls_long_number_values.json +1 -0
  43. data/src/test/resources/org/embulk/output/kintone/task/skip/update_always_skip_prefer_nulls_update_records.jsonl +2 -0
  44. data/src/test/resources/org/embulk/output/kintone/task/skip/update_always_skip_update_records.jsonl +5 -0
  45. data/src/test/resources/org/embulk/output/kintone/task/skip/update_never_skip_update_records.jsonl +6 -0
  46. data/src/test/resources/org/embulk/output/kintone/task/skip/update_prefer_nulls_update_records.jsonl +3 -0
  47. data/src/test/resources/org/embulk/output/kintone/task/skip/update_update_records.jsonl +6 -0
  48. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_add_records.jsonl +1 -0
  49. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_always_skip_prefer_nulls_string_single_line_text_add_values.json +1 -0
  50. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_always_skip_prefer_nulls_string_single_line_text_values.json +1 -0
  51. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_always_skip_prefer_nulls_update_records.jsonl +2 -0
  52. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_always_skip_string_single_line_text_add_values.json +1 -0
  53. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_always_skip_string_single_line_text_values.json +1 -0
  54. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_always_skip_update_records.jsonl +2 -0
  55. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_add_records.jsonl +4 -0
  56. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_prefer_nulls_add_records.jsonl +4 -0
  57. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_prefer_nulls_string_single_line_text_add_values.json +1 -0
  58. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_prefer_nulls_string_single_line_text_values.json +1 -0
  59. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_prefer_nulls_update_records.jsonl +2 -0
  60. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_string_single_line_text_add_values.json +1 -0
  61. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_string_single_line_text_values.json +1 -0
  62. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_never_skip_update_records.jsonl +2 -0
  63. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_prefer_nulls_add_records.jsonl +1 -0
  64. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_prefer_nulls_string_single_line_text_add_values.json +1 -0
  65. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_prefer_nulls_string_single_line_text_values.json +1 -0
  66. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_prefer_nulls_update_records.jsonl +2 -0
  67. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_string_single_line_text_add_values.json +1 -0
  68. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_string_single_line_text_values.json +1 -0
  69. data/src/test/resources/org/embulk/output/kintone/task/skip/upsert_update_records.jsonl +2 -0
  70. data/src/test/resources/org/embulk/output/kintone/task/skip_id/config.yml +1 -0
  71. data/src/test/resources/org/embulk/output/kintone/task/skip_id/input.csv +7 -0
  72. data/src/test/resources/org/embulk/output/kintone/task/skip_id/insert_add_records.jsonl +6 -0
  73. data/src/test/resources/org/embulk/output/kintone/task/skip_id/insert_always_skip_add_records.jsonl +6 -0
  74. data/src/test/resources/org/embulk/output/kintone/task/skip_id/insert_always_skip_prefer_nulls_add_records.jsonl +6 -0
  75. data/src/test/resources/org/embulk/output/kintone/task/skip_id/insert_never_skip_add_records.jsonl +6 -0
  76. data/src/test/resources/org/embulk/output/kintone/task/skip_id/insert_never_skip_prefer_nulls_add_records.jsonl +6 -0
  77. data/src/test/resources/org/embulk/output/kintone/task/skip_id/insert_prefer_nulls_add_records.jsonl +6 -0
  78. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_always_skip__id_add_values.json +1 -0
  79. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_always_skip__id_values.json +1 -0
  80. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_always_skip_prefer_nulls__id_add_values.json +1 -0
  81. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_always_skip_prefer_nulls__id_values.json +1 -0
  82. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_always_skip_prefer_nulls_update_records.jsonl +2 -0
  83. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_always_skip_update_records.jsonl +5 -0
  84. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_never_skip_update_records.jsonl +6 -0
  85. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_prefer_nulls_update_records.jsonl +3 -0
  86. data/src/test/resources/org/embulk/output/kintone/task/skip_id/update_update_records.jsonl +6 -0
  87. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert__id_add_values.json +1 -0
  88. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert__id_values.json +1 -0
  89. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_always_skip__id_add_values.json +1 -0
  90. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_always_skip__id_values.json +1 -0
  91. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_always_skip_prefer_nulls__id_add_values.json +1 -0
  92. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_always_skip_prefer_nulls__id_values.json +1 -0
  93. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_always_skip_prefer_nulls_update_records.jsonl +2 -0
  94. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_always_skip_update_records.jsonl +5 -0
  95. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip__id_add_values.json +1 -0
  96. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip__id_values.json +1 -0
  97. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip_add_records.jsonl +1 -0
  98. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip_prefer_nulls__id_add_values.json +1 -0
  99. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip_prefer_nulls__id_values.json +1 -0
  100. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip_prefer_nulls_add_records.jsonl +4 -0
  101. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip_prefer_nulls_update_records.jsonl +2 -0
  102. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_never_skip_update_records.jsonl +5 -0
  103. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_prefer_nulls__id_add_values.json +1 -0
  104. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_prefer_nulls__id_values.json +1 -0
  105. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_prefer_nulls_add_records.jsonl +3 -0
  106. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_prefer_nulls_update_records.jsonl +2 -0
  107. data/src/test/resources/org/embulk/output/kintone/task/skip_id/upsert_update_records.jsonl +5 -0
  108. metadata +131 -43
  109. data/classpath/embulk-output-kintone-1.1.0.jar +0 -0
  110. data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/upsert_add_records.jsonl +0 -0
  111. /data/src/test/resources/org/embulk/output/kintone/task/mode/{insert_add_ignore_nulls_records.jsonl → insert_ignore_nulls_add_records.jsonl} +0 -0
  112. /data/src/test/resources/org/embulk/output/kintone/task/mode/{insert_add_prefer_nulls_records.jsonl → insert_prefer_nulls_add_records.jsonl} +0 -0
  113. /data/src/test/resources/org/embulk/output/kintone/task/mode/{update_update_ignore_nulls_records.jsonl → update_ignore_nulls_update_records.jsonl} +0 -0
  114. /data/src/test/resources/org/embulk/output/kintone/task/mode/{update_update_prefer_nulls_records.jsonl → update_prefer_nulls_update_records.jsonl} +0 -0
  115. /data/src/test/resources/org/embulk/output/kintone/task/mode/{upsert_add_records.jsonl → upsert_never_skip_add_records.jsonl} +0 -0
  116. /data/src/test/resources/org/embulk/output/kintone/task/mode/{values.json → upsert_never_skip_double_single_line_text_values.json} +0 -0
  117. /data/src/test/resources/org/embulk/output/kintone/task/mode/{upsert_add_ignore_nulls_records.jsonl → upsert_never_skip_ignore_nulls_add_records.jsonl} +0 -0
  118. /data/src/test/resources/org/embulk/output/kintone/task/mode/{values_ignore_nulls.json → upsert_never_skip_ignore_nulls_double_single_line_text_values.json} +0 -0
  119. /data/src/test/resources/org/embulk/output/kintone/task/mode/{upsert_update_ignore_nulls_records.jsonl → upsert_never_skip_ignore_nulls_update_records.jsonl} +0 -0
  120. /data/src/test/resources/org/embulk/output/kintone/task/mode/{upsert_add_prefer_nulls_records.jsonl → upsert_never_skip_prefer_nulls_add_records.jsonl} +0 -0
  121. /data/src/test/resources/org/embulk/output/kintone/task/mode/{values_prefer_nulls.json → upsert_never_skip_prefer_nulls_double_single_line_text_values.json} +0 -0
  122. /data/src/test/resources/org/embulk/output/kintone/task/mode/{upsert_update_prefer_nulls_records.jsonl → upsert_never_skip_prefer_nulls_update_records.jsonl} +0 -0
  123. /data/src/test/resources/org/embulk/output/kintone/task/mode/{upsert_update_records.jsonl → upsert_never_skip_update_records.jsonl} +0 -0
  124. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{insert_add_ignore_nulls_records.jsonl → insert_ignore_nulls_add_records.jsonl} +0 -0
  125. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{insert_add_prefer_nulls_records.jsonl → insert_prefer_nulls_add_records.jsonl} +0 -0
  126. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{update_update_ignore_nulls_records.jsonl → update_ignore_nulls_update_records.jsonl} +0 -0
  127. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{update_update_prefer_nulls_records.jsonl → update_prefer_nulls_update_records.jsonl} +0 -0
  128. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{upsert_add_records.jsonl → upsert_never_skip_add_records.jsonl} +0 -0
  129. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{values.json → upsert_never_skip_double_single_line_text_values.json} +0 -0
  130. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{upsert_add_ignore_nulls_records.jsonl → upsert_never_skip_ignore_nulls_add_records.jsonl} +0 -0
  131. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{values_ignore_nulls.json → upsert_never_skip_ignore_nulls_double_single_line_text_values.json} +0 -0
  132. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{upsert_update_ignore_nulls_records.jsonl → upsert_never_skip_ignore_nulls_update_records.jsonl} +0 -0
  133. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{upsert_add_prefer_nulls_records.jsonl → upsert_never_skip_prefer_nulls_add_records.jsonl} +0 -0
  134. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{values_prefer_nulls.json → upsert_never_skip_prefer_nulls_double_single_line_text_values.json} +0 -0
  135. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{upsert_update_prefer_nulls_records.jsonl → upsert_never_skip_prefer_nulls_update_records.jsonl} +0 -0
  136. /data/src/test/resources/org/embulk/output/kintone/task/reduce/{upsert_update_records.jsonl → upsert_never_skip_update_records.jsonl} +0 -0
  137. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{insert_add_ignore_nulls_records.jsonl → insert_ignore_nulls_add_records.jsonl} +0 -0
  138. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{insert_add_prefer_nulls_records.jsonl → insert_prefer_nulls_add_records.jsonl} +0 -0
  139. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{update_update_ignore_nulls_records.jsonl → update_ignore_nulls_update_records.jsonl} +0 -0
  140. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{update_update_prefer_nulls_records.jsonl → update_prefer_nulls_update_records.jsonl} +0 -0
  141. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{values.json → upsert_never_skip_double_single_line_text_values.json} +0 -0
  142. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{upsert_add_ignore_nulls_records.jsonl → upsert_never_skip_ignore_nulls_add_records.jsonl} +0 -0
  143. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{values_ignore_nulls.json → upsert_never_skip_ignore_nulls_double_single_line_text_values.json} +0 -0
  144. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{upsert_update_ignore_nulls_records.jsonl → upsert_never_skip_ignore_nulls_update_records.jsonl} +0 -0
  145. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{upsert_add_prefer_nulls_records.jsonl → upsert_never_skip_prefer_nulls_add_records.jsonl} +0 -0
  146. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{values_prefer_nulls.json → upsert_never_skip_prefer_nulls_double_single_line_text_values.json} +0 -0
  147. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{upsert_update_prefer_nulls_records.jsonl → upsert_never_skip_prefer_nulls_update_records.jsonl} +0 -0
  148. /data/src/test/resources/org/embulk/output/kintone/task/reduce_subtable/{upsert_update_records.jsonl → upsert_never_skip_update_records.jsonl} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 38d9d369925e0cab9fa558716b9a939be4b1387e
4
- data.tar.gz: f4ae4a741548a48b042e1c4b79bf7e533ded0d31
3
+ metadata.gz: abd297c9f29bedc191c3abc3837ff3955fdde7df
4
+ data.tar.gz: 5be528c62b5f1985b756f311699f74370b05a52b
5
5
  SHA512:
6
- metadata.gz: 06d103f7c4036dd458f62955bee9b2b82aa2bb2719cb59f18a2a762bab5c892025b4dd7fb0b41647e0e9cf66e012916f60de1a48c1a6d41414af0447d8affb06
7
- data.tar.gz: ee848b7cfb53cc27c731724d32b6d5ffa9fe3336742fc1bbf24bd2b49d07f6f99439b478a0342051810ef94597471caded0f81caaf3aaff78203ce0ff20485d6
6
+ metadata.gz: 040f72edfe4cfe79b4bc0c303653efc6d1fb93b84db8d009df9bf845e6bd1e712d4c222412db5c22bf21a9b1315cf6029b30c359294c664972c0fe369ed50345
7
+ data.tar.gz: 808579e76d0a6d854583d0d834f487f9a102b7cb827030d5857f4f0268f310f5f854135790904b9551cca9b489c58311434b4117a53426581642c79acced3ff0
data/README.md CHANGED
@@ -26,6 +26,14 @@ kintone output plugin for Embulk stores app records from kintone.
26
26
  - **max_sort_memory**: Maximum memory usage for sorting input records (bytes in long, default is the estimated available memory, which is the approximate value of the JVM's current free memory)
27
27
  - **prefer_nulls**: Whether to set fields to null instead of default value of type when column is null (boolean, default is `false`)
28
28
  - **ignore_nulls**: Whether to completely ignore fields when column is null (boolean, default is `false`)
29
+ - **skip_if_non_existing_id_or_update_key**: The skip policy if the record corresponding to the id or update key does not exist (string `auto`, `never` or `always`, default is `auto`). No effect for insert mode.
30
+ - **auto**:
31
+ - **update mode**: Skip the record if no id or update key value is specified.
32
+ - **upsert mode**: Skip the record if corresponds to the id does not exist or no update key value is specified.
33
+ - **never**: Never skip the record even if corresponds to the id or update key does not exist.
34
+ - **update mode**: Throw exception if no id or update key value is specified.
35
+ - **upsert mode**: Insert the record if corresponds to the id or update key does not exist (also, if no id or update key value is specified).
36
+ - **always**: Always skip the record if corresponds to the id or update key does not exist (also, if no id or update key value is specified). update mode and upsert mode will the same behavior (only updated, never inserted).
29
37
  - **column_options** advanced: a key-value pairs where key is a column name and value is options for the column.
30
38
  - **field_code**: field code (string, required)
31
39
  - **type**: field type (string, required). See [this page](https://cybozu.dev/ja/kintone/docs/overview/field-types/#field-type-update) for list of available types. However, following types are not yet supported
@@ -0,0 +1,117 @@
1
+ package org.embulk.output.kintone;
2
+
3
+ import com.kintone.client.KintoneClientBuilder;
4
+ import com.kintone.client.RecordClient;
5
+ import com.kintone.client.model.app.field.FieldProperty;
6
+ import com.kintone.client.model.record.FieldType;
7
+ import java.io.IOException;
8
+ import java.util.Map;
9
+ import java.util.function.Supplier;
10
+ import org.embulk.config.ConfigException;
11
+ import org.embulk.output.kintone.record.Id;
12
+ import org.embulk.output.kintone.util.Lazy;
13
+ import org.embulk.spi.Column;
14
+ import org.embulk.spi.Schema;
15
+ import org.embulk.spi.type.Type;
16
+ import org.embulk.spi.type.Types;
17
+
18
+ public class KintoneClient implements AutoCloseable {
19
+ private final PluginTask task;
20
+ private final Schema schema;
21
+ private final com.kintone.client.KintoneClient client;
22
+ private final Map<String, FieldProperty> fields;
23
+
24
+ public static Lazy<KintoneClient> lazy(Supplier<PluginTask> task, Schema schema) {
25
+ return new Lazy<KintoneClient>() {
26
+ @Override
27
+ protected KintoneClient initialValue() {
28
+ return new KintoneClient(task.get(), schema);
29
+ }
30
+ };
31
+ }
32
+
33
+ private KintoneClient(PluginTask task, Schema schema) {
34
+ this.task = task;
35
+ this.schema = schema;
36
+ KintoneClientBuilder builder = KintoneClientBuilder.create("https://" + task.getDomain());
37
+ if (task.getGuestSpaceId().isPresent()) {
38
+ builder.setGuestSpaceId(task.getGuestSpaceId().get());
39
+ }
40
+ if (task.getBasicAuthUsername().isPresent() && task.getBasicAuthPassword().isPresent()) {
41
+ builder.withBasicAuth(task.getBasicAuthUsername().get(), task.getBasicAuthPassword().get());
42
+ }
43
+ if (task.getUsername().isPresent() && task.getPassword().isPresent()) {
44
+ builder.authByPassword(task.getUsername().get(), task.getPassword().get());
45
+ } else if (task.getToken().isPresent()) {
46
+ builder.authByApiToken(task.getToken().get());
47
+ } else {
48
+ throw new ConfigException("Username and password or token must be configured.");
49
+ }
50
+ client = builder.build();
51
+ fields = client.app().getFormFields(task.getAppId());
52
+ KintoneMode.of(task).validate(task, this);
53
+ }
54
+
55
+ public void validateIdOrUpdateKey(String columnName) {
56
+ Column column = getColumn(columnName);
57
+ if (column == null) {
58
+ throw new ConfigException("The column '" + columnName + "' for update does not exist.");
59
+ }
60
+ validateId(column);
61
+ validateUpdateKey(column);
62
+ }
63
+
64
+ public Column getColumn(String columnName) {
65
+ return schema.getColumns().stream()
66
+ .filter(column -> column.getName().equals(columnName))
67
+ .findFirst()
68
+ .orElse(null);
69
+ }
70
+
71
+ public FieldType getFieldType(String fieldCode) {
72
+ FieldProperty field = fields.get(fieldCode);
73
+ return field == null ? null : field.getType();
74
+ }
75
+
76
+ public RecordClient record() {
77
+ return client.record();
78
+ }
79
+
80
+ @Override
81
+ public void close() {
82
+ try {
83
+ client.close();
84
+ } catch (IOException e) {
85
+ throw new RuntimeException("kintone throw exception", e);
86
+ }
87
+ }
88
+
89
+ private void validateId(Column column) {
90
+ if (!column.getName().equals(Id.FIELD)) {
91
+ return;
92
+ }
93
+ Type type = column.getType();
94
+ if (!type.equals(Types.LONG)) {
95
+ throw new ConfigException("The id column must be 'long'.");
96
+ }
97
+ }
98
+
99
+ private void validateUpdateKey(Column column) {
100
+ if (column.getName().equals(Id.FIELD)) {
101
+ return;
102
+ }
103
+ String fieldCode = getFieldCode(column);
104
+ FieldType fieldType = getFieldType(fieldCode);
105
+ if (fieldType == null) {
106
+ throw new ConfigException("The field '" + fieldCode + "' for update does not exist.");
107
+ }
108
+ if (fieldType != FieldType.SINGLE_LINE_TEXT && fieldType != FieldType.NUMBER) {
109
+ throw new ConfigException("The update_key must be 'SINGLE_LINE_TEXT' or 'NUMBER'.");
110
+ }
111
+ }
112
+
113
+ private String getFieldCode(Column column) {
114
+ KintoneColumnOption option = task.getColumnOptions().get(column.getName());
115
+ return option != null ? option.getFieldCode() : column.getName();
116
+ }
117
+ }
@@ -13,6 +13,7 @@ import com.kintone.client.model.record.MultiSelectFieldValue;
13
13
  import com.kintone.client.model.record.NumberFieldValue;
14
14
  import com.kintone.client.model.record.OrganizationSelectFieldValue;
15
15
  import com.kintone.client.model.record.RadioButtonFieldValue;
16
+ import com.kintone.client.model.record.Record;
16
17
  import com.kintone.client.model.record.RichTextFieldValue;
17
18
  import com.kintone.client.model.record.SingleLineTextFieldValue;
18
19
  import com.kintone.client.model.record.SubtableFieldValue;
@@ -34,6 +35,8 @@ import org.embulk.output.kintone.deserializer.Deserializer;
34
35
  import org.embulk.spi.time.Timestamp;
35
36
  import org.embulk.spi.type.Type;
36
37
  import org.embulk.spi.type.Types;
38
+ import org.msgpack.value.ArrayValue;
39
+ import org.msgpack.value.StringValue;
37
40
  import org.msgpack.value.Value;
38
41
  import org.msgpack.value.ValueFactory;
39
42
 
@@ -49,6 +52,11 @@ public enum KintoneColumnType {
49
52
  return new SingleLineTextFieldValue(value);
50
53
  }
51
54
 
55
+ @Override
56
+ public String getValue(Record record, String fieldCode) {
57
+ return record.getSingleLineTextFieldValue(fieldCode);
58
+ }
59
+
52
60
  @Override
53
61
  public void setUpdateKey(UpdateKey updateKey, String field) {
54
62
  updateKey.setField(field);
@@ -60,7 +68,7 @@ public enum KintoneColumnType {
60
68
  }
61
69
 
62
70
  @Override
63
- public Value asValue(FieldValue value) {
71
+ public StringValue asValue(FieldValue value) {
64
72
  return ValueFactory.newString(((SingleLineTextFieldValue) value).getValue());
65
73
  }
66
74
 
@@ -81,7 +89,7 @@ public enum KintoneColumnType {
81
89
  }
82
90
 
83
91
  @Override
84
- public Value asValue(FieldValue value) {
92
+ public StringValue asValue(FieldValue value) {
85
93
  return ValueFactory.newString(((MultiLineTextFieldValue) value).getValue());
86
94
  }
87
95
 
@@ -102,7 +110,7 @@ public enum KintoneColumnType {
102
110
  }
103
111
 
104
112
  @Override
105
- public Value asValue(FieldValue value) {
113
+ public StringValue asValue(FieldValue value) {
106
114
  return ValueFactory.newString(((RichTextFieldValue) value).getValue());
107
115
  }
108
116
 
@@ -132,6 +140,11 @@ public enum KintoneColumnType {
132
140
  return (NumberFieldValue) getFieldValue(value.getEpochSecond(), option);
133
141
  }
134
142
 
143
+ @Override
144
+ public BigDecimal getValue(Record record, String fieldCode) {
145
+ return record.getNumberFieldValue(fieldCode);
146
+ }
147
+
135
148
  @Override
136
149
  public void setUpdateKey(UpdateKey updateKey, String field) {
137
150
  updateKey.setField(field);
@@ -143,8 +156,8 @@ public enum KintoneColumnType {
143
156
  }
144
157
 
145
158
  @Override
146
- public Value asValue(FieldValue value) {
147
- return ValueFactory.newString(((NumberFieldValue) value).getValue().toString());
159
+ public StringValue asValue(FieldValue value) {
160
+ return ValueFactory.newString(((NumberFieldValue) value).getValue().toPlainString());
148
161
  }
149
162
 
150
163
  @Override
@@ -164,7 +177,7 @@ public enum KintoneColumnType {
164
177
  }
165
178
 
166
179
  @Override
167
- public Value asValue(FieldValue value) {
180
+ public ArrayValue asValue(FieldValue value) {
168
181
  return ValueFactory.newArray(
169
182
  ((CheckBoxFieldValue) value)
170
183
  .getValues().stream().map(ValueFactory::newString).collect(Collectors.toList()));
@@ -187,7 +200,7 @@ public enum KintoneColumnType {
187
200
  }
188
201
 
189
202
  @Override
190
- public Value asValue(FieldValue value) {
203
+ public StringValue asValue(FieldValue value) {
191
204
  return ValueFactory.newString(((RadioButtonFieldValue) value).getValue());
192
205
  }
193
206
 
@@ -208,7 +221,7 @@ public enum KintoneColumnType {
208
221
  }
209
222
 
210
223
  @Override
211
- public Value asValue(FieldValue value) {
224
+ public ArrayValue asValue(FieldValue value) {
212
225
  return ValueFactory.newArray(
213
226
  ((MultiSelectFieldValue) value)
214
227
  .getValues().stream().map(ValueFactory::newString).collect(Collectors.toList()));
@@ -231,7 +244,7 @@ public enum KintoneColumnType {
231
244
  }
232
245
 
233
246
  @Override
234
- public Value asValue(FieldValue value) {
247
+ public StringValue asValue(FieldValue value) {
235
248
  return ValueFactory.newString(((DropDownFieldValue) value).getValue());
236
249
  }
237
250
 
@@ -336,7 +349,7 @@ public enum KintoneColumnType {
336
349
  }
337
350
 
338
351
  @Override
339
- public Value asValue(FieldValue value) {
352
+ public StringValue asValue(FieldValue value) {
340
353
  return ValueFactory.newString(((DateFieldValue) value).getValue().toString());
341
354
  }
342
355
 
@@ -378,7 +391,7 @@ public enum KintoneColumnType {
378
391
  }
379
392
 
380
393
  @Override
381
- public Value asValue(FieldValue value) {
394
+ public StringValue asValue(FieldValue value) {
382
395
  return ValueFactory.newString(((TimeFieldValue) value).getValue().toString());
383
396
  }
384
397
 
@@ -416,7 +429,7 @@ public enum KintoneColumnType {
416
429
  }
417
430
 
418
431
  @Override
419
- public Value asValue(FieldValue value) {
432
+ public StringValue asValue(FieldValue value) {
420
433
  return ValueFactory.newString(((DateTimeFieldValue) value).getValue().toString());
421
434
  }
422
435
 
@@ -437,7 +450,7 @@ public enum KintoneColumnType {
437
450
  }
438
451
 
439
452
  @Override
440
- public Value asValue(FieldValue value) {
453
+ public StringValue asValue(FieldValue value) {
441
454
  return ValueFactory.newString(((LinkFieldValue) value).getValue());
442
455
  }
443
456
 
@@ -540,6 +553,10 @@ public enum KintoneColumnType {
540
553
  }
541
554
  }
542
555
 
556
+ public Object getValue(Record Record, String fieldCode) {
557
+ throw new UnsupportedOperationException();
558
+ }
559
+
543
560
  public void setUpdateKey(UpdateKey updateKey, String field) {
544
561
  throw new UnsupportedOperationException();
545
562
  }
@@ -4,8 +4,12 @@ import com.kintone.client.model.record.FieldValue;
4
4
  import com.kintone.client.model.record.Record;
5
5
  import com.kintone.client.model.record.UpdateKey;
6
6
  import java.time.Instant;
7
+ import java.util.Arrays;
8
+ import java.util.List;
7
9
  import java.util.Map;
8
10
  import java.util.Set;
11
+ import org.embulk.output.kintone.record.Id;
12
+ import org.embulk.output.kintone.record.IdOrUpdateKey;
9
13
  import org.embulk.spi.Column;
10
14
  import org.embulk.spi.ColumnVisitor;
11
15
  import org.embulk.spi.PageReader;
@@ -14,6 +18,7 @@ import org.msgpack.value.Value;
14
18
  import org.msgpack.value.ValueFactory;
15
19
 
16
20
  public class KintoneColumnVisitor implements ColumnVisitor {
21
+ private static final List<String> BUILTIN_FIELD_CODES = Arrays.asList(Id.FIELD, "$revision");
17
22
  private final PageReader reader;
18
23
  private final Set<Column> derived;
19
24
  private final Map<String, KintoneColumnOption> options;
@@ -22,7 +27,7 @@ public class KintoneColumnVisitor implements ColumnVisitor {
22
27
  private final String reduceKeyName;
23
28
  private final String updateKeyName;
24
29
  private Record record;
25
- private UpdateKey updateKey;
30
+ private IdOrUpdateKey idOrUpdateKey;
26
31
 
27
32
  public KintoneColumnVisitor(
28
33
  PageReader reader,
@@ -55,8 +60,8 @@ public class KintoneColumnVisitor implements ColumnVisitor {
55
60
  this.record = record;
56
61
  }
57
62
 
58
- public void setUpdateKey(UpdateKey updateKey) {
59
- this.updateKey = updateKey;
63
+ public void setIdOrUpdateKey(IdOrUpdateKey idOrUpdateKey) {
64
+ this.idOrUpdateKey = idOrUpdateKey;
60
65
  }
61
66
 
62
67
  @Override
@@ -68,6 +73,9 @@ public class KintoneColumnVisitor implements ColumnVisitor {
68
73
  UpdateKey updateKey = getUpdateKey(column);
69
74
  KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.NUMBER);
70
75
  String fieldCode = getFieldCode(column);
76
+ if (isBuiltin(fieldCode)) {
77
+ return;
78
+ }
71
79
  if (isPreferNull(column)) {
72
80
  setNull(type, fieldCode, updateKey);
73
81
  } else if (reader.isNull(column)) {
@@ -82,10 +90,18 @@ public class KintoneColumnVisitor implements ColumnVisitor {
82
90
  if (isReduced(column) || isIgnoreNull(column)) {
83
91
  return;
84
92
  }
93
+ Id id = getId(column);
94
+ if (id != null) {
95
+ setIdValue(id, column);
96
+ return;
97
+ }
85
98
  KintoneColumnOption option = getOption(column);
86
99
  UpdateKey updateKey = getUpdateKey(column);
87
100
  KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.NUMBER);
88
101
  String fieldCode = getFieldCode(column);
102
+ if (isBuiltin(fieldCode)) {
103
+ return;
104
+ }
89
105
  if (isPreferNull(column)) {
90
106
  setNull(type, fieldCode, updateKey);
91
107
  } else if (reader.isNull(column)) {
@@ -104,6 +120,9 @@ public class KintoneColumnVisitor implements ColumnVisitor {
104
120
  UpdateKey updateKey = getUpdateKey(column);
105
121
  KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.NUMBER);
106
122
  String fieldCode = getFieldCode(column);
123
+ if (isBuiltin(fieldCode)) {
124
+ return;
125
+ }
107
126
  if (isPreferNull(column)) {
108
127
  setNull(type, fieldCode, updateKey);
109
128
  } else if (reader.isNull(column)) {
@@ -124,6 +143,9 @@ public class KintoneColumnVisitor implements ColumnVisitor {
124
143
  updateKey != null ? KintoneColumnType.SINGLE_LINE_TEXT : KintoneColumnType.MULTI_LINE_TEXT;
125
144
  KintoneColumnType type = KintoneColumnType.getType(option, defaultType);
126
145
  String fieldCode = getFieldCode(column);
146
+ if (isBuiltin(fieldCode)) {
147
+ return;
148
+ }
127
149
  if (isPreferNull(column)) {
128
150
  setNull(type, fieldCode, updateKey);
129
151
  } else if (reader.isNull(column)) {
@@ -142,6 +164,9 @@ public class KintoneColumnVisitor implements ColumnVisitor {
142
164
  UpdateKey updateKey = getUpdateKey(column);
143
165
  KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.DATETIME);
144
166
  String fieldCode = getFieldCode(column);
167
+ if (isBuiltin(fieldCode)) {
168
+ return;
169
+ }
145
170
  if (isPreferNull(column)) {
146
171
  setNull(type, fieldCode, updateKey);
147
172
  } else if (reader.isNull(column)) {
@@ -162,6 +187,9 @@ public class KintoneColumnVisitor implements ColumnVisitor {
162
187
  isDerived(column) ? KintoneColumnType.SUBTABLE : KintoneColumnType.MULTI_LINE_TEXT;
163
188
  KintoneColumnType type = KintoneColumnType.getType(option, defaultType);
164
189
  String fieldCode = getFieldCode(column);
190
+ if (isBuiltin(fieldCode)) {
191
+ return;
192
+ }
165
193
  if (isPreferNull(column)) {
166
194
  setNull(type, fieldCode, updateKey);
167
195
  } else if (reader.isNull(column)) {
@@ -171,6 +199,16 @@ public class KintoneColumnVisitor implements ColumnVisitor {
171
199
  }
172
200
  }
173
201
 
202
+ private void setIdValue(Id id, Column column) {
203
+ if (isPreferNull(column)) {
204
+ id.setValue(null);
205
+ } else if (reader.isNull(column)) {
206
+ id.setValue(0L);
207
+ } else {
208
+ id.setValue(reader.getLong(column));
209
+ }
210
+ }
211
+
174
212
  private void setNull(KintoneColumnType type, String fieldCode, UpdateKey updateKey) {
175
213
  if (updateKey != null) {
176
214
  type.setUpdateKey(updateKey, fieldCode);
@@ -265,8 +303,16 @@ public class KintoneColumnVisitor implements ColumnVisitor {
265
303
  return options.get(column.getName());
266
304
  }
267
305
 
306
+ private Id getId(Column column) {
307
+ return column.getName().equals(updateKeyName) && updateKeyName.equals(Id.FIELD)
308
+ ? idOrUpdateKey.getId()
309
+ : null;
310
+ }
311
+
268
312
  private UpdateKey getUpdateKey(Column column) {
269
- return updateKeyName != null && updateKeyName.equals(column.getName()) ? updateKey : null;
313
+ return column.getName().equals(updateKeyName) && !updateKeyName.equals(Id.FIELD)
314
+ ? idOrUpdateKey.getUpdateKey()
315
+ : null;
270
316
  }
271
317
 
272
318
  private boolean isReduced(Column column) {
@@ -284,4 +330,8 @@ public class KintoneColumnVisitor implements ColumnVisitor {
284
330
  private boolean isPreferNull(Column column) {
285
331
  return preferNulls && reader.isNull(column);
286
332
  }
333
+
334
+ private static boolean isBuiltin(String fieldCode) {
335
+ return BUILTIN_FIELD_CODES.contains(fieldCode);
336
+ }
287
337
  }
@@ -1,23 +1,71 @@
1
1
  package org.embulk.output.kintone;
2
2
 
3
+ import java.util.function.Consumer;
3
4
  import org.embulk.config.ConfigException;
5
+ import org.embulk.output.kintone.record.Id;
6
+ import org.embulk.output.kintone.record.Skip;
7
+ import org.embulk.spi.Page;
4
8
 
5
9
  public enum KintoneMode {
6
- INSERT("insert"),
7
- UPDATE("update"),
8
- UPSERT("upsert");
10
+ INSERT("insert") {
11
+ @Override
12
+ public void validate(PluginTask task, KintoneClient client) {
13
+ if (task.getUpdateKeyName().isPresent()) {
14
+ throw new ConfigException("When mode is insert, require no update_key.");
15
+ }
16
+ }
17
+
18
+ @Override
19
+ public void add(Page page, Skip skip, KintonePageOutput output) {
20
+ output.insertPage(page);
21
+ }
22
+ },
23
+ UPDATE("update") {
24
+ @Override
25
+ public void validate(PluginTask task, KintoneClient client) {
26
+ if (!task.getUpdateKeyName().isPresent() && client.getColumn(Id.FIELD) == null) {
27
+ throw new ConfigException("When mode is update, require update_key or id column.");
28
+ }
29
+ client.validateIdOrUpdateKey(task.getUpdateKeyName().orElse(Id.FIELD));
30
+ }
31
+
32
+ @Override
33
+ public void add(Page page, Skip skip, KintonePageOutput output) {
34
+ Consumer<Page> consumer = skip == Skip.ALWAYS ? output::upsertPage : output::updatePage;
35
+ consumer.accept(page);
36
+ }
37
+ },
38
+ UPSERT("upsert") {
39
+ @Override
40
+ public void validate(PluginTask task, KintoneClient client) {
41
+ if (!task.getUpdateKeyName().isPresent() && client.getColumn(Id.FIELD) == null) {
42
+ throw new ConfigException("When mode is upsert, require update_key or id column.");
43
+ }
44
+ client.validateIdOrUpdateKey(task.getUpdateKeyName().orElse(Id.FIELD));
45
+ }
46
+
47
+ @Override
48
+ public void add(Page page, Skip skip, KintonePageOutput output) {
49
+ output.upsertPage(page);
50
+ }
51
+ };
9
52
  private final String value;
10
53
 
11
54
  KintoneMode(String value) {
12
55
  this.value = value;
13
56
  }
14
57
 
58
+ public abstract void validate(PluginTask task, KintoneClient client);
59
+
60
+ public abstract void add(Page page, Skip skip, KintonePageOutput output);
61
+
15
62
  @Override
16
63
  public String toString() {
17
64
  return value;
18
65
  }
19
66
 
20
- public static KintoneMode getKintoneModeByValue(String value) {
67
+ public static KintoneMode of(PluginTask task) {
68
+ String value = task.getMode();
21
69
  for (KintoneMode mode : values()) {
22
70
  if (mode.toString().equals(value)) {
23
71
  return mode;
@@ -3,7 +3,6 @@ package org.embulk.output.kintone;
3
3
  import java.util.Collections;
4
4
  import java.util.List;
5
5
  import org.embulk.config.ConfigDiff;
6
- import org.embulk.config.ConfigException;
7
6
  import org.embulk.config.ConfigSource;
8
7
  import org.embulk.config.TaskReport;
9
8
  import org.embulk.config.TaskSource;
@@ -40,22 +39,6 @@ public class KintoneOutputPlugin implements OutputPlugin {
40
39
  @Override
41
40
  public TransactionalPageOutput open(TaskSource taskSource, Schema schema, int taskIndex) {
42
41
  PluginTask task = taskSource.loadTask(PluginTask.class);
43
- KintoneMode mode = KintoneMode.getKintoneModeByValue(task.getMode());
44
- switch (mode) {
45
- case INSERT:
46
- if (task.getUpdateKeyName().isPresent()) {
47
- throw new ConfigException("when mode is insert, require no update_key.");
48
- }
49
- break;
50
- case UPDATE:
51
- case UPSERT:
52
- if (!task.getUpdateKeyName().isPresent()) {
53
- throw new ConfigException("when mode is update or upsert, require update_key.");
54
- }
55
- break;
56
- default:
57
- throw new ConfigException(String.format("Unknown mode '%s'", task.getMode()));
58
- }
59
42
  return task.getReduceKeyName().isPresent()
60
43
  ? new ReducedPageOutput(schema, taskIndex)
61
44
  : new KintonePageOutput(task, schema);