You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2020/06/02 20:39:03 UTC
[beam] branch master updated: [BEAM-10027] Support for Kotlin-based
Beam Katas (#11761)
This is an automated email from the ASF dual-hosted git repository.
pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new efa8337 [BEAM-10027] Support for Kotlin-based Beam Katas (#11761)
efa8337 is described below
commit efa8337b3be5aa464dffb96733405e5fc636347a
Author: Rion Williams <ri...@gmail.com>
AuthorDate: Tue Jun 2 15:38:42 2020 -0500
[BEAM-10027] Support for Kotlin-based Beam Katas (#11761)
* initial commit and copy from existing java katas
* added kotlin dependencies to gradle
* updated course info and related README to reference Kotlin
* converted Introduction section and tests to Kotlin; updated course metadata
* converted Map section to Kotlin
* converted GroupByKey section to Kotlin
* converted CoGroupByKey section to Kotlin
* converted remaining Combine tasks to Kotlin
* minor readability improvements to tests and test naming
* additional tests / readability clean-up
* converted Flatten section to Kotlin
* updated test to follow previous naming conventions
* converted Partition lesson to Kotlin
* converted Side Input section to Kotlin
* updated test name to follow convention
* converted Side Output lesson to Kotlin
* converted remaining Core Transform sections and tests
* converted Filter lessons to Kotlin
* reformatted earlier conversions to mimic Java readability/spacing
* updated consistent formatting per existing Java examples
* additional formatting changes
* additional formatting changes for previous lessons
* converted remaining Common Transforms lessons
* converted IO lessons
* converted Windowing lessons to Kotlin
* converted Triggers lessons to Kotlin
* additional formatting; ensuring tests pass as expected
* cleanup kotlin-specific warnings for core transforms
* updated remaining core transforms
* cleaned up common transforms
* cleaned up io transforms
* cleaned up windowing lessons
* updated triggering and examples lessons
* removed html task documentation and updated placeholders
* added placeholders and updated descriptions
* updated descrptions and placeholders
* updated cogroupbykey placeholders and descriptions
* updated combine lesson descriptions and placeholders
* updated flatten lesson descriptions, etc.
* updated partition lessons, descriptions, and placeholders
* updated side output lessons, descriptions, and placeholders
* updated side input/output lessons, descriptions, and placeholders
* updated branching and composite transform lessons, descriptions, and placeholders
* updated filter lessons, descriptions, and placeholders
* updated aggregation lessons, descriptions, and placeholders
* updated withkeys lessons, descriptions, and placeholders
* updated io transforms, lessons, and placeholders
* updated windowing lessons, descriptions, and placeholders
* updated trigger lessons, descriptions, and placeholders
* updated remaining triggers and examples
* fixed bad placeholder
* updates for initial stepik course creation
* removed lingering html files
* improved placeholder positioning and answer
* improved combine function by exposing accumulator at task-time; removed cruft
* removed unnecessary scaffolding for binary combine lesson
* more placeholder updates/clean-up
* more placeholder updates
* reformatted per Kotlin style guide; updated placeholders through core transforms
* updated placeholders for Common Transforms, IO, and Windowing sections
* updated Triggers and Examples section placeholders
* changed WordAlphabet to data class
* converted classes to data classes where applicable; removed unused imports
* updated stepik course and adjusted course summary metadata
* added missing data class
* minor requested changes
* fixed accumulator syntax
* adjust windowed event to data class
* updated stepik course
* added 2 space indenting, updated placeholders, removed unused imports
* updated course post formatting changes
* removed returns from Map-related placeholders; updated course
* added licensing information to task metadata
* added missing license header to Introduction section
---
.../commontransforms/aggregation/count/Task.kt | 46 +++++
.../Aggregation/Count/task-info.yaml | 29 ++++
.../Aggregation/Count/task-remote-info.yaml | 2 +
.../Common Transforms/Aggregation/Count/task.md | 27 +++
.../commontransforms/aggregation/count/TaskTest.kt | 43 +++++
.../katas/commontransforms/aggregation/max/Task.kt | 46 +++++
.../Aggregation/Max/task-info.yaml | 29 ++++
.../Aggregation/Max/task-remote-info.yaml | 2 +
.../Common Transforms/Aggregation/Max/task.md | 27 +++
.../commontransforms/aggregation/max/TaskTest.kt | 43 +++++
.../commontransforms/aggregation/mean/Task.kt | 46 +++++
.../Aggregation/Mean/task-info.yaml | 29 ++++
.../Aggregation/Mean/task-remote-info.yaml | 2 +
.../Common Transforms/Aggregation/Mean/task.md | 27 +++
.../commontransforms/aggregation/mean/TaskTest.kt | 43 +++++
.../katas/commontransforms/aggregation/min/Task.kt | 46 +++++
.../Aggregation/Min/task-info.yaml | 29 ++++
.../Aggregation/Min/task-remote-info.yaml | 2 +
.../Common Transforms/Aggregation/Min/task.md | 27 +++
.../commontransforms/aggregation/min/TaskTest.kt | 43 +++++
.../katas/commontransforms/aggregation/sum/Task.kt | 45 +++++
.../Aggregation/Sum/task-info.yaml | 29 ++++
.../Aggregation/Sum/task-remote-info.yaml | 2 +
.../Common Transforms/Aggregation/Sum/task.md | 27 +++
.../commontransforms/aggregation/sum/TaskTest.kt | 42 +++++
.../Common Transforms/Aggregation/lesson-info.yaml | 25 +++
.../Aggregation/lesson-remote-info.yaml | 3 +
.../katas/commontransforms/filter/filter/Task.kt | 47 +++++
.../Common Transforms/Filter/Filter/task-info.yaml | 29 ++++
.../Filter/Filter/task-remote-info.yaml | 2 +
.../kotlin/Common Transforms/Filter/Filter/task.md | 30 ++++
.../commontransforms/filter/filter/TaskTest.kt | 43 +++++
.../katas/commontransforms/filter/pardo/Task.kt | 57 +++++++
.../Common Transforms/Filter/ParDo/task-info.yaml | 29 ++++
.../Filter/ParDo/task-remote-info.yaml | 2 +
.../kotlin/Common Transforms/Filter/ParDo/task.md | 30 ++++
.../commontransforms/filter/pardo/TaskTest.kt | 43 +++++
.../Common Transforms/Filter/lesson-info.yaml | 22 +++
.../Filter/lesson-remote-info.yaml | 3 +
.../katas/commontransforms/withkeys/Task.kt | 53 ++++++
.../WithKeys/WithKeys/task-info.yaml | 29 ++++
.../WithKeys/WithKeys/task-remote-info.yaml | 2 +
.../Common Transforms/WithKeys/WithKeys/task.md | 33 ++++
.../katas/commontransforms/withkeys/TaskTest.kt | 51 ++++++
.../Common Transforms/WithKeys/lesson-info.yaml | 21 +++
.../WithKeys/lesson-remote-info.yaml | 3 +
.../kotlin/Common Transforms/section-info.yaml | 23 +++
.../Common Transforms/section-remote-info.yaml | 2 +
.../katas/coretransforms/branching/Task.kt | 63 +++++++
.../Branching/Branching/task-info.yaml | 32 ++++
.../Branching/Branching/task-remote-info.yaml | 2 +
.../Core Transforms/Branching/Branching/task.md | 32 ++++
.../katas/coretransforms/branching/TaskTest.kt | 47 +++++
.../Core Transforms/Branching/lesson-info.yaml | 21 +++
.../Branching/lesson-remote-info.yaml | 3 +
.../katas/coretransforms/cogroupbykey/Task.kt | 84 +++++++++
.../coretransforms/cogroupbykey/WordsAlphabet.kt | 24 +++
.../CoGroupByKey/CoGroupByKey/task-info.yaml | 31 ++++
.../CoGroupByKey/task-remote-info.yaml | 2 +
.../CoGroupByKey/CoGroupByKey/task.md | 43 +++++
.../katas/coretransforms/cogroupbykey/TaskTest.kt | 54 ++++++
.../Core Transforms/CoGroupByKey/lesson-info.yaml | 21 +++
.../CoGroupByKey/lesson-remote-info.yaml | 3 +
.../combine/binarycombinefnlambda/Task.kt | 52 ++++++
.../Combine/BinaryCombineFn Lambda/task-info.yaml | 29 ++++
.../BinaryCombineFn Lambda/task-remote-info.yaml | 2 +
.../Combine/BinaryCombineFn Lambda/task.md | 40 +++++
.../combine/binarycombinefnlambda/TaskTest.kt | 47 +++++
.../coretransforms/combine/binarycombinefn/Task.kt | 59 +++++++
.../Combine/BinaryCombineFn/task-info.yaml | 29 ++++
.../Combine/BinaryCombineFn/task-remote-info.yaml | 2 +
.../Combine/BinaryCombineFn/task.md | 45 +++++
.../combine/binarycombinefn/TaskTest.kt | 47 +++++
.../coretransforms/combine/combineperkey/Task.kt | 63 +++++++
.../Combine/Combine PerKey/task-info.yaml | 32 ++++
.../Combine/Combine PerKey/task-remote-info.yaml | 2 +
.../Core Transforms/Combine/Combine PerKey/task.md | 46 +++++
.../combine/combineperkey/TaskTest.kt | 49 ++++++
.../katas/coretransforms/combine/combinefn/Task.kt | 79 +++++++++
.../Combine/CombineFn/task-info.yaml | 29 ++++
.../Combine/CombineFn/task-remote-info.yaml | 2 +
.../Core Transforms/Combine/CombineFn/task.md | 47 +++++
.../coretransforms/combine/combinefn/TaskTest.kt | 43 +++++
.../katas/coretransforms/combine/simple/Task.kt | 53 ++++++
.../Combine/Simple Function/task-info.yaml | 29 ++++
.../Combine/Simple Function/task-remote-info.yaml | 2 +
.../Combine/Simple Function/task.md | 44 +++++
.../coretransforms/combine/simple/TaskTest.kt | 43 +++++
.../Core Transforms/Combine/lesson-info.yaml | 25 +++
.../Combine/lesson-remote-info.yaml | 3 +
.../katas/coretransforms/composite/Task.kt | 62 +++++++
.../Composite Transform/task-info.yaml | 29 ++++
.../Composite Transform/task-remote-info.yaml | 2 +
.../Composite Transform/task.md | 47 +++++
.../katas/coretransforms/composite/TaskTest.kt | 44 +++++
.../Composite Transform/lesson-info.yaml | 21 +++
.../Composite Transform/lesson-remote-info.yaml | 3 +
.../coretransforms/dofnadditionalparams/Task.kt | 31 ++++
.../DoFn Additional Parameters/task-info.yaml | 25 +++
.../task-remote-info.yaml | 2 +
.../DoFn Additional Parameters/task.md | 38 +++++
.../dofnadditionalparams/TaskTest.kt | 20 +++
.../DoFn Additional Parameters/lesson-info.yaml | 21 +++
.../lesson-remote-info.yaml | 3 +
.../learning/katas/coretransforms/flatten/Task.kt | 58 +++++++
.../Core Transforms/Flatten/Flatten/task-info.yaml | 29 ++++
.../Flatten/Flatten/task-remote-info.yaml | 2 +
.../kotlin/Core Transforms/Flatten/Flatten/task.md | 39 +++++
.../katas/coretransforms/flatten/TaskTest.kt | 49 ++++++
.../Core Transforms/Flatten/lesson-info.yaml | 21 +++
.../Flatten/lesson-remote-info.yaml | 3 +
.../katas/coretransforms/groupbykey/Task.kt | 58 +++++++
.../GroupByKey/GroupByKey/task-info.yaml | 29 ++++
.../GroupByKey/GroupByKey/task-remote-info.yaml | 2 +
.../Core Transforms/GroupByKey/GroupByKey/task.md | 43 +++++
.../katas/coretransforms/groupbykey/TaskTest.kt | 52 ++++++
.../Core Transforms/GroupByKey/lesson-info.yaml | 21 +++
.../GroupByKey/lesson-remote-info.yaml | 3 +
.../coretransforms/map/flatmapelements/Task.kt | 54 ++++++
.../Map/FlatMapElements/task-info.yaml | 29 ++++
.../Map/FlatMapElements/task-remote-info.yaml | 2 +
.../Core Transforms/Map/FlatMapElements/task.md | 39 +++++
.../coretransforms/map/flatmapelements/TaskTest.kt | 44 +++++
.../katas/coretransforms/map/mapelements/Task.kt | 52 ++++++
.../Core Transforms/Map/MapElements/task-info.yaml | 29 ++++
.../Map/MapElements/task-remote-info.yaml | 2 +
.../kotlin/Core Transforms/Map/MapElements/task.md | 38 +++++
.../coretransforms/map/mapelements/TaskTest.kt | 43 +++++
.../coretransforms/map/pardoonetomany/Task.kt | 55 ++++++
.../Map/ParDo OneToMany/task-info.yaml | 29 ++++
.../Map/ParDo OneToMany/task-remote-info.yaml | 2 +
.../Core Transforms/Map/ParDo OneToMany/task.md | 37 ++++
.../coretransforms/map/pardoonetomany/TaskTest.kt | 41 +++++
.../katas/coretransforms/map/pardo/Task.kt | 54 ++++++
.../Core Transforms/Map/ParDo/task-info.yaml | 29 ++++
.../Map/ParDo/task-remote-info.yaml | 2 +
.../katas/kotlin/Core Transforms/Map/ParDo/task.md | 40 +++++
.../katas/coretransforms/map/pardo/TaskTest.kt | 44 +++++
.../kotlin/Core Transforms/Map/lesson-info.yaml | 24 +++
.../Core Transforms/Map/lesson-remote-info.yaml | 3 +
.../katas/coretransforms/partition/Task.kt | 57 +++++++
.../Partition/Partition/task-info.yaml | 29 ++++
.../Partition/Partition/task-remote-info.yaml | 2 +
.../Core Transforms/Partition/Partition/task.md | 44 +++++
.../katas/coretransforms/partition/TaskTest.kt | 44 +++++
.../Core Transforms/Partition/lesson-info.yaml | 21 +++
.../Partition/lesson-remote-info.yaml | 3 +
.../katas/coretransforms/sideinput/Person.kt | 22 +++
.../katas/coretransforms/sideinput/Task.kt | 90 ++++++++++
.../Side Input/Side Input/src/task.md | 52 ++++++
.../Side Input/Side Input/task-info.yaml | 34 ++++
.../Side Input/Side Input/task-remote-info.yaml | 2 +
.../Core Transforms/Side Input/Side Input/task.md | 52 ++++++
.../katas/coretransforms/sideinput/TaskTest.kt | 72 ++++++++
.../Core Transforms/Side Input/lesson-info.yaml | 21 +++
.../Side Input/lesson-remote-info.yaml | 3 +
.../katas/coretransforms/sideoutput/Task.kt | 68 ++++++++
.../Side Output/Side Output/src/task.md | 42 +++++
.../Side Output/Side Output/task-info.yaml | 29 ++++
.../Side Output/Side Output/task-remote-info.yaml | 2 +
.../Side Output/Side Output/task.md | 42 +++++
.../katas/coretransforms/sideoutput/TaskTest.kt | 49 ++++++
.../Core Transforms/Side Output/lesson-info.yaml | 21 +++
.../Side Output/lesson-remote-info.yaml | 3 +
.../katas/kotlin/Core Transforms/section-info.yaml | 31 ++++
.../Core Transforms/section-remote-info.yaml | 2 +
.../beam/learning/katas/examples/wordcount/Task.kt | 66 +++++++
.../Examples/Word Count/Word Count/task-info.yaml | 29 ++++
.../Word Count/Word Count/task-remote-info.yaml | 2 +
.../kotlin/Examples/Word Count/Word Count/task.md | 33 ++++
.../learning/katas/examples/wordcount/TaskTest.kt | 53 ++++++
.../kotlin/Examples/Word Count/lesson-info.yaml | 21 +++
.../Examples/Word Count/lesson-remote-info.yaml | 3 +
learning/katas/kotlin/Examples/section-info.yaml | 21 +++
.../katas/kotlin/Examples/section-remote-info.yaml | 2 +
.../beam/learning/katas/io/builtinios/Task.kt | 31 ++++
.../IO/Built-in IOs/Built-in IOs/task-info.yaml | 25 +++
.../Built-in IOs/task-remote-info.yaml | 2 +
.../kotlin/IO/Built-in IOs/Built-in IOs/task.md | 29 ++++
.../beam/learning/katas/io/builtinios/TaskTest.kt | 20 +++
.../katas/kotlin/IO/Built-in IOs/lesson-info.yaml | 21 +++
.../kotlin/IO/Built-in IOs/lesson-remote-info.yaml | 3 +
.../kotlin/IO/TextIO/TextIO Read/countries.txt | 10 ++
.../beam/learning/katas/io/textio/read/Task.kt | 54 ++++++
.../kotlin/IO/TextIO/TextIO Read/task-info.yaml | 34 ++++
.../IO/TextIO/TextIO Read/task-remote-info.yaml | 2 +
.../katas/kotlin/IO/TextIO/TextIO Read/task.md | 44 +++++
.../beam/learning/katas/io/textio/read/TaskTest.kt | 53 ++++++
learning/katas/kotlin/IO/TextIO/lesson-info.yaml | 21 +++
.../katas/kotlin/IO/TextIO/lesson-remote-info.yaml | 3 +
learning/katas/kotlin/IO/section-info.yaml | 22 +++
learning/katas/kotlin/IO/section-remote-info.yaml | 2 +
.../apache/beam/learning/katas/intro/hello/Task.kt | 43 +++++
.../Hello Beam/Hello Beam/task-info.yaml | 29 ++++
.../Hello Beam/Hello Beam/task-remote-info.yaml | 2 +
.../Introduction/Hello Beam/Hello Beam/task.md | 0
.../beam/learning/katas/intro/hello/TaskTest.kt | 40 +++++
.../Introduction/Hello Beam/lesson-info.yaml | 21 +++
.../Hello Beam/lesson-remote-info.yaml | 3 +
.../katas/kotlin/Introduction/section-info.yaml | 21 +++
.../kotlin/Introduction/section-remote-info.yaml | 2 +
learning/katas/kotlin/README.md | 31 ++++
.../katas/triggers/earlytriggers/GenerateEvent.kt | 41 +++++
.../learning/katas/triggers/earlytriggers/Task.kt | 62 +++++++
.../Early Triggers/Early Triggers/task-info.yaml | 31 ++++
.../Early Triggers/task-remote-info.yaml | 2 +
.../Triggers/Early Triggers/Early Triggers/task.md | 60 +++++++
.../katas/triggers/earlytriggers/TaskTest.kt | 64 +++++++
.../Triggers/Early Triggers/lesson-info.yaml | 21 +++
.../Early Triggers/lesson-remote-info.yaml | 3 +
.../triggers/eventtimetriggers/GenerateEvent.kt | 41 +++++
.../katas/triggers/eventtimetriggers/Task.kt | 57 +++++++
.../Event Time Triggers/task-info.yaml | 31 ++++
.../Event Time Triggers/task-remote-info.yaml | 2 +
.../Event Time Triggers/task.md | 72 ++++++++
.../katas/triggers/eventtimetriggers/TaskTest.kt | 67 ++++++++
.../Triggers/Event Time Triggers/lesson-info.yaml | 21 +++
.../Event Time Triggers/lesson-remote-info.yaml | 3 +
.../triggers/windowaccummode/GenerateEvent.kt | 41 +++++
.../katas/triggers/windowaccummode/Task.kt | 62 +++++++
.../Window Accumulation Mode/task-info.yaml | 31 ++++
.../Window Accumulation Mode/task-remote-info.yaml | 2 +
.../Window Accumulation Mode/task.md | 65 +++++++
.../katas/triggers/windowaccummode/TaskTest.kt | 64 +++++++
.../Window Accumulation Mode/lesson-info.yaml | 21 +++
.../lesson-remote-info.yaml | 3 +
learning/katas/kotlin/Triggers/section-info.yaml | 23 +++
.../katas/kotlin/Triggers/section-remote-info.yaml | 2 +
.../katas/windowing/addingtimestamp/pardo/Event.kt | 23 +++
.../katas/windowing/addingtimestamp/pardo/Task.kt | 61 +++++++
.../Adding Timestamp/ParDo/task-info.yaml | 31 ++++
.../Adding Timestamp/ParDo/task-remote-info.yaml | 2 +
.../Windowing/Adding Timestamp/ParDo/task.md | 46 +++++
.../windowing/addingtimestamp/pardo/TaskTest.kt | 77 +++++++++
.../addingtimestamp/withtimestamps/Event.kt | 23 +++
.../addingtimestamp/withtimestamps/Task.kt | 55 ++++++
.../Adding Timestamp/WithTimestamps/task-info.yaml | 31 ++++
.../WithTimestamps/task-remote-info.yaml | 2 +
.../Adding Timestamp/WithTimestamps/task.md | 39 +++++
.../addingtimestamp/withtimestamps/TaskTest.kt | 75 ++++++++
.../Windowing/Adding Timestamp/lesson-info.yaml | 22 +++
.../Adding Timestamp/lesson-remote-info.yaml | 3 +
.../learning/katas/windowing/fixedwindow/Task.kt | 66 +++++++
.../Fixed Time Window/task-info.yaml | 31 ++++
.../Fixed Time Window/task-remote-info.yaml | 2 +
.../Fixed Time Window/Fixed Time Window/task.md | 53 ++++++
.../katas/windowing/fixedwindow/TaskTest.kt | 81 +++++++++
.../katas/windowing/fixedwindow/WindowedEvent.kt | 22 +++
.../Windowing/Fixed Time Window/lesson-info.yaml | 21 +++
.../Fixed Time Window/lesson-remote-info.yaml | 3 +
learning/katas/kotlin/Windowing/section-info.yaml | 22 +++
.../kotlin/Windowing/section-remote-info.yaml | 2 +
learning/katas/kotlin/build.gradle | 134 +++++++++++++++
learning/katas/kotlin/course-info.yaml | 32 ++++
learning/katas/kotlin/course-remote-info.yaml | 2 +
.../katas/kotlin/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55190 bytes
.../gradle/wrapper/gradle-wrapper.properties | 23 +++
learning/katas/kotlin/gradlew | 190 +++++++++++++++++++++
learning/katas/kotlin/gradlew.bat | 102 +++++++++++
learning/katas/kotlin/settings.gradle | 43 +++++
learning/katas/kotlin/util/resources/log4j2.xml | 31 ++++
.../src/org/apache/beam/learning/katas/util/Log.kt | 63 +++++++
.../apache/beam/learning/katas/util/ContainsKvs.kt | 58 +++++++
.../apache/beam/learning/katas/util/KvMatcher.kt | 47 +++++
264 files changed, 8214 insertions(+)
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Count/src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt
new file mode 100644
index 0000000..5f689c3
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.count
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Long> {
+ return input.apply(Count.globally())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-info.yaml
new file mode 100644
index 0000000..5718c4c
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1599
+ length: 29
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-remote-info.yaml
new file mode 100644
index 0000000..0e9dafb
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326891
+update_date: Sat, 30 May 2020 18:48:45 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task.md
new file mode 100644
index 0000000..1c4eba0
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task.md
@@ -0,0 +1,27 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Aggregation - Count
+-------------------
+
+**Kata:** Count the number of elements from an input.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html">
+ Count</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Count/test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt
new file mode 100644
index 0000000..a979bd7
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.count
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.count.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @Transient
+ @get:Rule
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun common_transforms_aggregation_count() {
+ val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(10L)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt
new file mode 100644
index 0000000..cab0f68
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.max
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Max
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(Max.integersGlobally())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-info.yaml
new file mode 100644
index 0000000..aa6cfca
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1594
+ length: 35
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-remote-info.yaml
new file mode 100644
index 0000000..6e6314a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326899
+update_date: Sat, 30 May 2020 18:48:55 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task.md
new file mode 100644
index 0000000..541a380
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task.md
@@ -0,0 +1,27 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Aggregation - Max
+-----------------
+
+**Kata:** Compute the maximum of the elements from an input.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Max.html">
+ Max</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Max/test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt
new file mode 100644
index 0000000..e17b1fc
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.max
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.max.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun common_transforms_aggregation_max() {
+ val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(10)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt
new file mode 100644
index 0000000..0c4943d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.mean
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Mean
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Double> {
+ return input.apply(Mean.globally())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-info.yaml
new file mode 100644
index 0000000..6f46aa6
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1599
+ length: 28
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-remote-info.yaml
new file mode 100644
index 0000000..bd2f905
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326897
+update_date: Sat, 30 May 2020 18:48:51 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task.md
new file mode 100644
index 0000000..b08fd97
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task.md
@@ -0,0 +1,27 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Aggregation - Mean
+------------------
+
+**Kata:** Compute the mean/average of all elements from an input.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Mean.html">
+ Mean</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt
new file mode 100644
index 0000000..48657a8
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.mean
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.mean.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun common_transforms_aggregation_mean() {
+ val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(5.5)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Min/src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt
new file mode 100644
index 0000000..7d1c95d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.min
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Min
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(Min.integersGlobally())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-info.yaml
new file mode 100644
index 0000000..5fbe869
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1594
+ length: 35
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-remote-info.yaml
new file mode 100644
index 0000000..0d5fbea
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326898
+update_date: Sat, 30 May 2020 18:48:53 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task.md
new file mode 100644
index 0000000..da5b319
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task.md
@@ -0,0 +1,27 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Aggregation - Min
+-----------------
+
+**Kata:** Compute the minimum of the elements from an input.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Min.html">
+ Min</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Min/test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt
new file mode 100644
index 0000000..ffcfee1
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.min
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.min.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun common_transforms_aggregation_min() {
+ val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(1)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt
new file mode 100644
index 0000000..1dce924
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.sum
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Sum
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(Sum.integersGlobally())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-info.yaml
new file mode 100644
index 0000000..f2b427d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt
+ visible: false
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1581
+ length: 35
+ placeholder_text: TODO()
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-remote-info.yaml
new file mode 100644
index 0000000..4660c8e
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326894
+update_date: Sat, 30 May 2020 18:48:47 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task.md
new file mode 100644
index 0000000..2031bba
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task.md
@@ -0,0 +1,27 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Aggregation - Sum
+-----------------
+
+**Kata:** Compute the sum of all elements from an input.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Sum.html">
+ Sum</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt
new file mode 100644
index 0000000..3e6d586
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.sum
+
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun common_transforms_aggregation_sum() {
+ val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ val numbers = testPipeline.apply(values)
+
+ val results = Task.applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(55)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/lesson-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-info.yaml
new file mode 100644
index 0000000..8ea5f25
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-info.yaml
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Count
+- Sum
+- Mean
+- Min
+- Max
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/lesson-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-remote-info.yaml
new file mode 100644
index 0000000..45fb600
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358533
+update_date: Wed, 20 May 2020 20:28:33 UTC
+unit: 342734
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt b/learning/katas/kotlin/Common Transforms/Filter/Filter/src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt
new file mode 100644
index 0000000..1e34761
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.filter
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Filter
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(Filter.by(SerializableFunction { number: Int -> number % 2 == 0 }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/task-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-info.yaml
new file mode 100644
index 0000000..ccfec4b
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1654
+ length: 79
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-remote-info.yaml
new file mode 100644
index 0000000..142dd53
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326890
+update_date: Sat, 30 May 2020 18:48:43 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/task.md b/learning/katas/kotlin/Common Transforms/Filter/Filter/task.md
new file mode 100644
index 0000000..e499074
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/task.md
@@ -0,0 +1,30 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Filter
+------
+
+The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.
+
+**Kata:** Implement a filter function that filters out the odd numbers by using
+[Filter](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Filter.html).
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Filter.html">
+ Filter.by(...)</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Filter/Filter/test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt
new file mode 100644
index 0000000..57efeba
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.filter
+
+import org.apache.beam.learning.katas.commontransforms.filter.filter.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun common_transforms_filter_filter() {
+ val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(2, 4, 6, 8, 10)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt b/learning/katas/kotlin/Common Transforms/Filter/ParDo/src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt
new file mode 100644
index 0000000..181e31a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.pardo
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(
+ ParDo.of(object : DoFn<Int, Int>() {
+ @ProcessElement
+ fun processElement(context: ProcessContext, out: OutputReceiver<Int>) {
+ val number = context.element()
+ if (number % 2 == 1) {
+ out.output(number)
+ }
+ }
+ })
+ )
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-info.yaml
new file mode 100644
index 0000000..dcd5326
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1636
+ length: 301
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-remote-info.yaml
new file mode 100644
index 0000000..352082b
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326889
+update_date: Sat, 30 May 2020 18:48:41 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/task.md b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task.md
new file mode 100644
index 0000000..be21a28
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task.md
@@ -0,0 +1,30 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Filter using ParDo
+------------------
+
+**Kata:** Implement a filter function that filters out the even numbers by using
+[DoFn](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html).
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo</a> with
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+ DoFn</a> and only output the intended element.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Filter/ParDo/test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt
new file mode 100644
index 0000000..0f5a485
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.pardo
+
+import org.apache.beam.learning.katas.commontransforms.filter.pardo.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun common_transforms_filter_pardo() {
+ val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(1, 3, 5, 7, 9)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/lesson-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/lesson-info.yaml
new file mode 100644
index 0000000..93f7b5a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/lesson-info.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- ParDo
+- Filter
diff --git a/learning/katas/kotlin/Common Transforms/Filter/lesson-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/lesson-remote-info.yaml
new file mode 100644
index 0000000..f0d6a9f
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358532
+update_date: Wed, 20 May 2020 20:28:26 UTC
+unit: 342733
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt
new file mode 100644
index 0000000..778481d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.withkeys
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.WithKeys
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val words = pipeline.apply(
+ Create.of("apple", "banana", "cherry", "durian", "guava", "melon")
+ )
+
+ val output = applyTransform(words)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<String>): PCollection<KV<String, String>> {
+ return input.apply(WithKeys
+ .of { fruit: String -> fruit.substring(0, 1) }
+ .withKeyType(TypeDescriptors.strings())
+ )
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-info.yaml
new file mode 100644
index 0000000..015ef56
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1731
+ length: 125
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-remote-info.yaml
new file mode 100644
index 0000000..5361a97
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326900
+update_date: Sat, 30 May 2020 18:48:58 UTC
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task.md b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task.md
new file mode 100644
index 0000000..15738d6
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task.md
@@ -0,0 +1,33 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+WithKeys
+--------
+
+**Kata:** Convert each fruit name into a KV of its first letter and itself, e.g.
+`apple => KV.of("a", "apple")`
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/WithKeys.html">
+ WithKeys</a>.
+</div>
+
+<div class="hint">
+ If using a lambda in Java 8, <code>withKeyType(TypeDescriptor)</code> must be called on the
+ result PTransform.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt
new file mode 100644
index 0000000..268bdcc
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.withkeys
+
+import org.apache.beam.learning.katas.commontransforms.withkeys.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun `Common Transforms - WithKeys - WithKeys`() {
+ val numbers = testPipeline.apply(
+ Create.of("apple", "banana", "cherry", "durian", "guava", "melon")
+ )
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(
+ KV.of("a", "apple"),
+ KV.of("b", "banana"),
+ KV.of("c", "cherry"),
+ KV.of("d", "durian"),
+ KV.of("g", "guava"),
+ KV.of("m", "melon")
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/lesson-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-info.yaml
new file mode 100644
index 0000000..1179567
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- WithKeys
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/lesson-remote-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-remote-info.yaml
new file mode 100644
index 0000000..f6b42c2
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358534
+update_date: Wed, 20 May 2020 20:28:44 UTC
+unit: 342735
diff --git a/learning/katas/kotlin/Common Transforms/section-info.yaml b/learning/katas/kotlin/Common Transforms/section-info.yaml
new file mode 100644
index 0000000..b32b98a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/section-info.yaml
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Filter
+- Aggregation
+- WithKeys
diff --git a/learning/katas/kotlin/Common Transforms/section-remote-info.yaml b/learning/katas/kotlin/Common Transforms/section-remote-info.yaml
new file mode 100644
index 0000000..bc801ce
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133889
+update_date: Wed, 20 May 2020 20:28:25 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt b/learning/katas/kotlin/Core Transforms/Branching/Branching/src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt
new file mode 100644
index 0000000..25185f8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.branching
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5))
+
+ val mult5Results = applyMultiply5Transform(numbers)
+ val mult10Results = applyMultiply10Transform(numbers)
+
+ mult5Results.apply("Log multiply 5", Log.ofElements("Multiplied by 5: "))
+ mult10Results.apply("Log multiply 10", Log.ofElements("Multiplied by 10: "))
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyMultiply5Transform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(
+ "Multiply by 5", MapElements
+ .into(TypeDescriptors.integers())
+ .via(SerializableFunction { num: Int -> num * 5 })
+ )
+ }
+
+ @JvmStatic
+ fun applyMultiply10Transform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(
+ "Multiply by 10", MapElements
+ .into(TypeDescriptors.integers())
+ .via(SerializableFunction { num: Int -> num * 10 })
+ )
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/task-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-info.yaml
new file mode 100644
index 0000000..581f2d6
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-info.yaml
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1893
+ length: 154
+ placeholder_text: TODO()
+ - offset: 2153
+ length: 156
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-remote-info.yaml
new file mode 100644
index 0000000..8f3b7b8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326886
+update_date: Sat, 30 May 2020 18:51:41 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/task.md b/learning/katas/kotlin/Core Transforms/Branching/Branching/task.md
new file mode 100644
index 0000000..3677fa9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/task.md
@@ -0,0 +1,32 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Branching
+---------
+
+You can use the same PCollection as input for multiple transforms without consuming the input or
+altering it.
+
+**Kata:** Branch out the numbers to two different transforms: one transform is multiplying each
+number by 5 and the other transform is multiplying each number by 10.
+
+<div class="hint">
+ Refer to the Beam Design Your Pipeline Guide
+ <a href="https://beam.apache.org/documentation/pipelines/design-your-pipeline/#multiple-transforms-process-the-same-pcollection">
+ "Multiple transforms process the same PCollection"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Branching/Branching/test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt
new file mode 100644
index 0000000..34c55a1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.branching
+
+import org.apache.beam.learning.katas.coretransforms.branching.Task.applyMultiply10Transform
+import org.apache.beam.learning.katas.coretransforms.branching.Task.applyMultiply5Transform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_branching_branching() {
+ val values = Create.of(1, 2, 3, 4, 5)
+ val numbers = testPipeline.apply(values)
+
+ val mult5Results = applyMultiply5Transform(numbers)
+ val mult10Results = applyMultiply10Transform(numbers)
+
+ PAssert.that(mult5Results).containsInAnyOrder(5, 10, 15, 20, 25)
+
+ PAssert.that(mult10Results).containsInAnyOrder(10, 20, 30, 40, 50)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Branching/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/lesson-info.yaml
new file mode 100644
index 0000000..25ecc7c
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Branching
diff --git a/learning/katas/kotlin/Core Transforms/Branching/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/lesson-remote-info.yaml
new file mode 100644
index 0000000..19d2d8d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358529
+update_date: Wed, 20 May 2020 20:28:09 UTC
+unit: 342730
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt
new file mode 100644
index 0000000..b1f442c
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.cogroupbykey
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.*
+import org.apache.beam.sdk.transforms.join.CoGbkResult
+import org.apache.beam.sdk.transforms.join.CoGroupByKey
+import org.apache.beam.sdk.transforms.join.KeyedPCollectionTuple
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TupleTag
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val fruits = pipeline.apply(
+ "Fruits",
+ Create.of("apple", "banana", "cherry")
+ )
+
+ val countries = pipeline.apply(
+ "Countries",
+ Create.of("australia", "brazil", "canada")
+ )
+
+ val output = applyTransform(fruits, countries)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(fruits: PCollection<String>, countries: PCollection<String>): PCollection<String> {
+ val fruitsTag = TupleTag<String>()
+ val countriesTag = TupleTag<String>()
+
+ val mapToAlphabetKv = MapElements
+ .into(TypeDescriptors.kvs(TypeDescriptors.strings(), TypeDescriptors.strings()))
+ .via(SerializableFunction { word: String -> KV.of(word.substring(0, 1), word) })
+
+ val fruitsPColl = fruits.apply("Fruit to KV", mapToAlphabetKv)
+ val countriesPColl = countries.apply("Country to KV", mapToAlphabetKv)
+
+ return KeyedPCollectionTuple
+ .of(fruitsTag, fruitsPColl)
+ .and(countriesTag, countriesPColl)
+ .apply(CoGroupByKey.create())
+ .apply(ParDo.of(object : DoFn<KV<String, CoGbkResult>, String>() {
+ @ProcessElement
+ fun processElement(@Element element: KV<String, CoGbkResult>, out: OutputReceiver<String>) {
+ val alphabet = element.key
+ val coGbkResult = element.value
+
+ val fruit = coGbkResult.getOnly(fruitsTag)
+ val country = coGbkResult.getOnly(countriesTag)
+
+ out.output(WordsAlphabet(alphabet, fruit, country).toString())
+ }
+ }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt
new file mode 100644
index 0000000..95c401a
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.cogroupbykey
+
+data class WordsAlphabet(private val alphabet: String?, private val fruit: String, private val country: String) {
+ override fun toString(): String {
+ return "WordsAlphabet{alphabet='$alphabet', fruit='$fruit', country='$country'}"
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-info.yaml
new file mode 100644
index 0000000..a371983
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt
+ visible: true
+ placeholders:
+ - offset: 2039
+ length: 1060
+ placeholder_text: TODO()
+- name: src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt
+ visible: true
+- name: test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-remote-info.yaml
new file mode 100644
index 0000000..fc69d68
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326877
+update_date: Sat, 30 May 2020 18:48:13 UTC
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task.md b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task.md
new file mode 100644
index 0000000..8b24f7a
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task.md
@@ -0,0 +1,43 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+CoGroupByKey
+------------
+
+CoGroupByKey performs a relational join of two or more key/value PCollections that have the same
+key type.
+
+**Kata:** Implement a
+[CoGroupByKey](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/join/CoGroupByKey.html)
+transform that join words by its first alphabetical letter, and then produces the toString()
+representation of the WordsAlphabet model.
+
+<div class="hint">
+ Refer to <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/join/CoGroupByKey.html">
+ CoGroupByKey</a>,
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/values/TupleTag.html">
+ TupleTag</a>, and
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/join/CoGbkResult.html">
+ CoGbkResult</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#cogroupbykey">
+ "CoGroupByKey"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt
new file mode 100644
index 0000000..7a348fb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.cogroupbykey
+
+import org.apache.beam.learning.katas.coretransforms.cogroupbykey.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_cogroupbykey_cogroupbykey() {
+ val fruits = testPipeline.apply(
+ "Fruits",
+ Create.of("apple", "banana", "cherry")
+ )
+
+ val countries = testPipeline.apply(
+ "Countries",
+ Create.of("australia", "brazil", "canada")
+ )
+
+ val results = applyTransform(fruits, countries)
+
+ PAssert.that(results).containsInAnyOrder(
+ "WordsAlphabet{alphabet='a', fruit='apple', country='australia'}",
+ "WordsAlphabet{alphabet='b', fruit='banana', country='brazil'}",
+ "WordsAlphabet{alphabet='c', fruit='cherry', country='canada'}"
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-info.yaml
new file mode 100644
index 0000000..273c077
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- CoGroupByKey
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-remote-info.yaml
new file mode 100644
index 0000000..29dd24d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358523
+update_date: Wed, 20 May 2020 20:27:27 UTC
+unit: 342724
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt
new file mode 100644
index 0000000..8e7bd47
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefnlambda
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+import java.math.BigInteger
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(
+ Create.of(
+ BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+ BigInteger.valueOf(40), BigInteger.valueOf(50)
+ )
+ )
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<BigInteger>): PCollection<BigInteger> {
+ return input.apply(Combine.globally(BigInteger::add))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-info.yaml
new file mode 100644
index 0000000..cc5d325
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1777
+ length: 46
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-remote-info.yaml
new file mode 100644
index 0000000..bda3554
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326880
+update_date: Sat, 30 May 2020 18:48:20 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task.md b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task.md
new file mode 100644
index 0000000..45a3e4d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task.md
@@ -0,0 +1,40 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Combine - BinaryCombineFn Lambda
+--------------------------------
+
+BinaryCombineFn is used for implementing combiners that are more easily expressed as binary
+operations.
+
+Since Beam v2.13.0, you can also use lambda or method reference in order to create the
+BinaryCombineFn.
+
+**Kata:** Implement the summation of BigInteger using lambda or method reference.
+
+<div class="hint">
+ Refer to
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/SerializableBiFunction.html">
+ SerializableBiFunction</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#combine">
+ "Combine"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt
new file mode 100644
index 0000000..09d5551
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefnlambda
+
+import org.apache.beam.learning.katas.coretransforms.combine.binarycombinefnlambda.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+import java.math.BigInteger
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_combine_binarycombinefn_lambda() {
+ val values = Create.of(
+ BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+ BigInteger.valueOf(40), BigInteger.valueOf(50)
+ )
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(BigInteger.valueOf(150))
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt
new file mode 100644
index 0000000..f483dd7
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefn
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Combine.BinaryCombineFn
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+import java.math.BigInteger
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(
+ Create.of(
+ BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+ BigInteger.valueOf(40), BigInteger.valueOf(50)
+ )
+ )
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<BigInteger>): PCollection<BigInteger> {
+ return input.apply(Combine.globally(SumBigIntegerFn()))
+ }
+
+ internal class SumBigIntegerFn : BinaryCombineFn<BigInteger>() {
+ override fun apply(left: BigInteger, right: BigInteger): BigInteger {
+ return left.add(right)
+ }
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-info.yaml
new file mode 100644
index 0000000..f0bb107
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1971
+ length: 104
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-remote-info.yaml
new file mode 100644
index 0000000..9fde7d9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326915
+update_date: Sat, 30 May 2020 18:50:08 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task.md b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task.md
new file mode 100644
index 0000000..ea026b1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task.md
@@ -0,0 +1,45 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Combine - BinaryCombineFn
+-------------------------
+
+Combine is a Beam transform for combining collections of elements or values in your data. When you
+apply a Combine transform, you must provide the function that contains the logic for combining the
+elements or values. The combining function should be commutative and associative, as the function
+is not necessarily invoked exactly once on all values with a given key. Because the input data
+(including the value collection) may be distributed across multiple workers, the combining function
+might be called multiple times to perform partial combining on subsets of the value collection.
+
+BinaryCombineFn is used for implementing combiners that are more easily expressed as binary
+operations.
+
+**Kata:** Implement the summation of BigInteger using
+[Combine.BinaryCombineFn](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html).
+
+<div class="hint">
+ Extend the
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html">
+ Combine.BinaryCombineFn</a> class that counts the sum of the number.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#combine">
+ "Combine"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt
new file mode 100644
index 0000000..4ca5139
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefn
+
+import org.apache.beam.learning.katas.coretransforms.combine.binarycombinefn.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+import java.math.BigInteger
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_combine_binarycombinefn() {
+ val values = Create.of(
+ BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+ BigInteger.valueOf(40), BigInteger.valueOf(50)
+ )
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(BigInteger.valueOf(150))
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt
new file mode 100644
index 0000000..f762ef1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combineperkey
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Combine.BinaryCombineFn
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ const val PLAYER_1 = "Player 1"
+ const val PLAYER_2 = "Player 2"
+ const val PLAYER_3 = "Player 3"
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val scores = pipeline.apply(
+ Create.of(
+ KV.of(PLAYER_1, 15), KV.of(PLAYER_2, 10), KV.of(PLAYER_1, 100),
+ KV.of(PLAYER_3, 25), KV.of(PLAYER_2, 75)
+ )
+ )
+
+ val output = applyTransform(scores)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<KV<String, Int>>): PCollection<KV<String, Int>> {
+ return input.apply<PCollection<KV<String, Int>>>(Combine.perKey(SumIntBinaryCombineFn()))
+ }
+
+ internal class SumIntBinaryCombineFn : BinaryCombineFn<Int>() {
+ override fun apply(left: Int, right: Int): Int {
+ return left + right
+ }
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-info.yaml
new file mode 100644
index 0000000..95a9502
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-info.yaml
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1950
+ length: 82
+ placeholder_text: TODO()
+ - offset: 2108
+ length: 80
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-remote-info.yaml
new file mode 100644
index 0000000..f273b81
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326881
+update_date: Sat, 30 May 2020 18:48:22 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task.md b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task.md
new file mode 100644
index 0000000..3f80616
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task.md
@@ -0,0 +1,46 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Combine - Combine PerKey
+------------------------
+
+After creating a keyed PCollection (for example, by using a GroupByKey transform), a common pattern
+is to combine the collection of values associated with each key into a single, merged value. This
+pattern of a GroupByKey followed by merging the collection of values is equivalent to Combine
+PerKey transform. The combine function you supply to Combine PerKey must be an associative
+reduction function or a subclass of CombineFn.
+
+**Kata:** Implement the sum of scores per player using
+[Combine.perKey](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/CombineFnBase.GlobalCombineFn.html).
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/CombineFnBase.GlobalCombineFn.html">
+ Combine.perKey(GlobalCombineFn)</a>.
+</div>
+
+<div class="hint">
+ Extend the
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html">
+ Combine.BinaryCombineFn</a> class that counts the sum of the number.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#combining-values-in-a-keyed-pcollection">
+ "Combining values in a keyed PCollection"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt
new file mode 100644
index 0000000..199bd30
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combineperkey
+
+import org.apache.beam.learning.katas.coretransforms.combine.combineperkey.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_combine_combine_perkey() {
+ val values = Create.of(
+ KV.of(Task.PLAYER_1, 15), KV.of(Task.PLAYER_2, 10), KV.of(Task.PLAYER_1, 100),
+ KV.of(Task.PLAYER_3, 25), KV.of(Task.PLAYER_2, 75)
+ )
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(
+ KV.of(Task.PLAYER_1, 115), KV.of(Task.PLAYER_2, 85), KV.of(Task.PLAYER_3, 25)
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt
new file mode 100644
index 0000000..97935aa
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combinefn
+
+import org.apache.beam.learning.katas.coretransforms.combine.combinefn.Task.AverageFn.Accum
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Combine.CombineFn
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+import java.io.Serializable
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(10, 20, 50, 70, 90))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Double> {
+ return input.apply(Combine.globally(AverageFn()))
+ }
+
+ internal class AverageFn : CombineFn<Int, Accum, Double>() {
+ internal data class Accum(var sum: Int = 0, var count: Int = 0) : Serializable
+
+ override fun createAccumulator(): Accum {
+ return Accum()
+ }
+
+ override fun addInput(accumulator: Accum, input: Int): Accum {
+ accumulator.sum += input
+ accumulator.count++
+
+ return accumulator
+ }
+
+ override fun mergeAccumulators(accumulators: Iterable<Accum>): Accum {
+ val merged = createAccumulator()
+
+ for (accumulator in accumulators) {
+ merged.sum += accumulator.sum
+ merged.count += accumulator.count
+ }
+
+ return merged
+ }
+
+ override fun extractOutput(accumulator: Accum): Double {
+ return accumulator.sum.toDouble() / accumulator.count
+ }
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-info.yaml
new file mode 100644
index 0000000..4ed3edb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1894
+ length: 710
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-remote-info.yaml
new file mode 100644
index 0000000..9758afb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326879
+update_date: Sat, 30 May 2020 18:50:05 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task.md b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task.md
new file mode 100644
index 0000000..13bce44
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task.md
@@ -0,0 +1,47 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Combine - CombineFn
+-------------------
+
+Combine is a Beam transform for combining collections of elements or values in your data. When you
+apply a Combine transform, you must provide the function that contains the logic for combining the
+elements or values. The combining function should be commutative and associative, as the function
+is not necessarily invoked exactly once on all values with a given key. Because the input data
+(including the value collection) may be distributed across multiple workers, the combining function
+might be called multiple times to perform partial combining on subsets of the value collection.
+
+Complex combination operations might require you to create a subclass of CombineFn that has an
+accumulation type distinct from the input/output type. You should use CombineFn if the combine
+function requires a more sophisticated accumulator, must perform additional pre- or post-processing,
+might change the output type, or takes the key into account.
+
+**Kata:** Implement the average of numbers using
+[Combine.CombineFn](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.CombineFn.html).
+
+<div class="hint">
+ Extend the
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.CombineFn.html">
+ Combine.CombineFn</a> class that counts the average of the number.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#advanced-combines">
+ "Advanced combinations using CombineFn"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt
new file mode 100644
index 0000000..7a612d5
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combinefn
+
+import org.apache.beam.learning.katas.coretransforms.combine.combinefn.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_combine_combinefn() {
+ val values = Create.of(10, 20, 50, 70, 90)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(48.0)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt
new file mode 100644
index 0000000..98a2103
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.simple
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(10, 30, 50, 70, 90))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(Combine.globally(SumIntegerFn()))
+ }
+
+ internal class SumIntegerFn : SerializableFunction<Iterable<Int>, Int> {
+ override fun apply(input: Iterable<Int>): Int {
+ return input.sum()
+ }
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-info.yaml
new file mode 100644
index 0000000..38c1766
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1786
+ length: 78
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-remote-info.yaml
new file mode 100644
index 0000000..5162bbd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326878
+update_date: Sat, 30 May 2020 18:48:15 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task.md b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task.md
new file mode 100644
index 0000000..b20fb9d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task.md
@@ -0,0 +1,44 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Combine - Simple Function
+-------------------------
+
+Combine is a Beam transform for combining collections of elements or values in your data. When you
+apply a Combine transform, you must provide the function that contains the logic for combining the
+elements or values. The combining function should be commutative and associative, as the function
+is not necessarily invoked exactly once on all values with a given key. Because the input data
+(including the value collection) may be distributed across multiple workers, the combining function
+might be called multiple times to perform partial combining on subsets of the value collection.
+
+Simple combine operations, such as sums, can usually be implemented as a simple function.
+
+**Kata:** Implement the summation of numbers using
+[Combine.globally(SerializableFunction)](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/SerializableFunction.html).
+
+<div class="hint">
+ Implement the
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/SerializableFunction.html#apply-InputT-">
+ SerializableFunction.apply</a> method that performs the summation of the Iterable.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#simple-combines">
+ "Simple combinations using simple functions"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt
new file mode 100644
index 0000000..0a0a2fd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.simple
+
+import org.apache.beam.learning.katas.coretransforms.combine.simple.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_combine_simple_function() {
+ val values = Create.of(10, 30, 50, 70, 90)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(250)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/lesson-info.yaml
new file mode 100644
index 0000000..b275018
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/lesson-info.yaml
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Simple Function
+- CombineFn
+- BinaryCombineFn
+- BinaryCombineFn Lambda
+- Combine PerKey
diff --git a/learning/katas/kotlin/Core Transforms/Combine/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/lesson-remote-info.yaml
new file mode 100644
index 0000000..8faec31
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358524
+update_date: Wed, 20 May 2020 20:27:36 UTC
+unit: 342725
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt
new file mode 100644
index 0000000..6e103cd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.composite
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.*
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import java.util.*
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ pipeline
+ .apply(Create.of("1,2,3,4,5", "6,7,8,9,10"))
+ .apply(ExtractAndMultiplyNumbers())
+ .apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ internal class ExtractAndMultiplyNumbers : PTransform<PCollection<String>, PCollection<Int>>() {
+ override fun expand(input: PCollection<String>): PCollection<Int> {
+ return input
+ .apply(ParDo.of(object : DoFn<String, Int>() {
+ @ProcessElement
+ fun processElement(@Element numbers: String, out: OutputReceiver<Int>) {
+ Arrays.stream(
+ numbers.split(",")
+ .toTypedArray()
+ )
+ .forEach { numStr: String -> out.output(numStr.toInt()) }
+ }
+ }))
+ .apply(
+ MapElements
+ .into(TypeDescriptors.integers())
+ .via(SerializableFunction { number: Int -> number * 10 })
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-info.yaml
new file mode 100644
index 0000000..8a0f9f6
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1605
+ length: 622
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-remote-info.yaml
new file mode 100644
index 0000000..cf842b9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326887
+update_date: Sat, 30 May 2020 18:50:17 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task.md b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task.md
new file mode 100644
index 0000000..45854bf
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task.md
@@ -0,0 +1,47 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Composite Transform
+-------------------
+
+Transforms can have a nested structure, where a complex transform performs multiple simpler
+transforms (such as more than one ParDo, Combine, GroupByKey, or even other composite transforms).
+These transforms are called composite transforms. Nesting multiple transforms inside a single
+composite transform can make your code more modular and easier to understand.
+
+To create your own composite transform, create a subclass of the PTransform class and override the
+expand method to specify the actual processing logic. You can then use this transform just as you
+would a built-in transform from the Beam SDK. For the PTransform class type parameters, you pass
+the PCollection types that your transform takes as input, and produces as output. Within your
+PTransform subclass, you’ll need to override the expand method. The expand method is where you add
+the processing logic for the PTransform. Your override of expand must accept the appropriate type
+of input PCollection as a parameter, and specify the output PCollection as the return value.
+
+**Kata:** Please implement a composite transform "ExtractAndMultiplyNumbers" that extracts numbers
+from comma separated line and then multiplies each number by 10.
+
+<div class="hint">
+ Refer to <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/PTransform.html">
+ PTransform</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#composite-transforms">
+ "Composite transforms"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt
new file mode 100644
index 0000000..dbc7d6f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.composite
+
+import org.apache.beam.learning.katas.coretransforms.composite.Task.ExtractAndMultiplyNumbers
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_composite_transform_composite_transform() {
+ val values = Create.of("1,2,3,4,5", "6,7,8,9,10")
+
+ val results = testPipeline
+ .apply(values)
+ .apply(ExtractAndMultiplyNumbers())
+
+ PAssert.that(results).containsInAnyOrder(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-info.yaml
new file mode 100644
index 0000000..177eab1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Composite Transform
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-remote-info.yaml
new file mode 100644
index 0000000..4f61026
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358530
+update_date: Wed, 20 May 2020 20:28:14 UTC
+unit: 342731
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt
new file mode 100644
index 0000000..553abad
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.dofnadditionalparams
+
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ pipeline.run()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-info.yaml
new file mode 100644
index 0000000..a00ae43
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-info.yaml
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt
+ visible: true
+- name: test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-remote-info.yaml
new file mode 100644
index 0000000..1ce2f88
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326888
+update_date: Sat, 30 May 2020 18:48:38 UTC
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task.md b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task.md
new file mode 100644
index 0000000..32657dc
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task.md
@@ -0,0 +1,38 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+DoFn Additional Parameters
+--------------------------
+
+In addition to the element and the OutputReceiver, Beam will populate other parameters to your
+DoFn’s @ProcessElement method. Any combination of these parameters can be added to your process
+method in any order.
+
+* **Timestamp**: To access the timestamp of an input element, add a parameter annotated with
+@Timestamp of type Instant
+* **Window**: To access the window an input element falls into, add a parameter of the type of
+the window used for the input PCollection.
+* **PaneInfo**: When triggers are used, Beam provides a PaneInfo object that contains information
+about the current firing. Using PaneInfo you can determine whether this is an early or a late
+firing, and how many times this window has already fired for this key.
+* **PipelineOptions**: The PipelineOptions for the current pipeline can always be accessed in a
+process method by adding it as a parameter.
+
+Refer to the Beam Programming Guide
+["Accessing additional parameters in your DoFn"](https://beam.apache.org/documentation/programming-guide/#other-dofn-parameters)
+section for more information.
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt
new file mode 100644
index 0000000..f20e39f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.dofnadditionalparams
+
+class TaskTest
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-info.yaml
new file mode 100644
index 0000000..1a41bfb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- DoFn Additional Parameters
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-remote-info.yaml
new file mode 100644
index 0000000..e79ba35
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358531
+update_date: Wed, 20 May 2020 20:28:20 UTC
+unit: 342732
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt
new file mode 100644
index 0000000..466df99
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.flatten
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Flatten
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionList
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val wordsStartingWithA = pipeline.apply(
+ "Words starting with A",
+ Create.of("apple", "ant", "arrow")
+ )
+
+ val wordsStartingWithB = pipeline.apply(
+ "Words starting with B",
+ Create.of("ball", "book", "bow")
+ )
+
+ val output = applyTransform(wordsStartingWithA, wordsStartingWithB)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(words1: PCollection<String>, words2: PCollection<String>): PCollection<String> {
+ return PCollectionList
+ .of(words1)
+ .and(words2)
+ .apply(Flatten.pCollections())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-info.yaml
new file mode 100644
index 0000000..7b1dc84
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1888
+ length: 89
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-remote-info.yaml
new file mode 100644
index 0000000..7aeed74
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326882
+update_date: Sat, 30 May 2020 18:48:25 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task.md b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task.md
new file mode 100644
index 0000000..5bf19ba
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task.md
@@ -0,0 +1,39 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Flatten
+-------
+
+Flatten is a Beam transform for PCollection objects that store the same data type. Flatten merges
+multiple PCollection objects into a single logical PCollection.
+
+**Kata:** Implement a
+[Flatten](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Flatten.html)
+transform that merges two PCollection of words into a single PCollection.
+
+<div class="hint">
+ Refer to
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Flatten.html">
+ Flatten</a> to solve this problem.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#flatten">
+ "Flatten"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt
new file mode 100644
index 0000000..acbad01
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.flatten
+
+import org.apache.beam.learning.katas.coretransforms.flatten.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_flatten_flatten() {
+ val wordsStartingWithA = testPipeline.apply(
+ "Words starting with A",
+ Create.of("apple", "ant", "arrow")
+ )
+ val wordsStartingWithB = testPipeline.apply(
+ "Words starting with B",
+ Create.of("ball", "book", "bow")
+ )
+
+ val results = applyTransform(wordsStartingWithA, wordsStartingWithB)
+
+ PAssert.that(results).containsInAnyOrder("apple", "ant", "arrow", "ball", "book", "bow")
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/lesson-info.yaml
new file mode 100644
index 0000000..fd01c86
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Flatten
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/lesson-remote-info.yaml
new file mode 100644
index 0000000..66bfb18
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358525
+update_date: Wed, 20 May 2020 20:27:47 UTC
+unit: 342726
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt
new file mode 100644
index 0000000..9a55ee7
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.groupbykey
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.GroupByKey
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val words = pipeline.apply(
+ Create.of("apple", "ball", "car", "bear", "cheetah", "ant")
+ )
+
+ val output = applyTransform(words)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<String>): PCollection<KV<String, Iterable<String>>> {
+ return input
+ .apply(
+ MapElements
+ .into(TypeDescriptors.kvs(TypeDescriptors.strings(), TypeDescriptors.strings()))
+ .via(SerializableFunction { word: String -> KV.of(word.substring(0, 1), word) })
+ )
+ .apply(GroupByKey.create())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-info.yaml
new file mode 100644
index 0000000..b22c4e9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1858
+ length: 263
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-remote-info.yaml
new file mode 100644
index 0000000..1ee3f72
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326876
+update_date: Sat, 30 May 2020 18:48:11 UTC
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task.md b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task.md
new file mode 100644
index 0000000..cfaa2eb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task.md
@@ -0,0 +1,43 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+GroupByKey
+----------
+
+GroupByKey is a Beam transform for processing collections of key/value pairs. It’s a parallel
+reduction operation, analogous to the Shuffle phase of a Map/Shuffle/Reduce-style algorithm. The
+input to GroupByKey is a collection of key/value pairs that represents a multimap, where the
+collection contains multiple pairs that have the same key, but different values. Given such a
+collection, you use GroupByKey to collect all of the values associated with each unique key.
+
+**Kata:** Implement a
+[GroupByKey](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/GroupByKey.html)
+transform that groups words by its first letter.
+
+<div class="hint">
+ Refer to <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/values/KV.html">
+ KV</a> and
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/GroupByKey.html">
+ GroupByKey</a> to solve this problem.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#groupbykey">
+ "GroupByKey"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt
new file mode 100644
index 0000000..5a7dea9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.groupbykey
+
+import com.google.common.collect.ImmutableList
+import org.apache.beam.learning.katas.coretransforms.groupbykey.Task.applyTransform
+import org.apache.beam.learning.katas.util.ContainsKvs
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_groupbykey_groupbykey() {
+ val values = Create.of("apple", "ball", "car", "bear", "cheetah", "ant")
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).satisfies(
+ ContainsKvs.containsKvs(
+ KV.of("a", ImmutableList.of("apple", "ant")),
+ KV.of("b", ImmutableList.of("ball", "bear")),
+ KV.of("c", ImmutableList.of("car", "cheetah"))
+ )
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-info.yaml
new file mode 100644
index 0000000..5de9eb6
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- GroupByKey
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-remote-info.yaml
new file mode 100644
index 0000000..83166a3
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358522
+update_date: Wed, 20 May 2020 20:27:23 UTC
+unit: 342723
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt
new file mode 100644
index 0000000..65c0c55
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.flatmapelements
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.FlatMapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val sentences = pipeline.apply(Create.of("Apache Beam", "Unified Batch and Streaming"))
+
+ val output = applyTransform(sentences)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<String>): PCollection<String> {
+ return input.apply(
+ FlatMapElements
+ .into(TypeDescriptors.strings())
+ .via(SerializableFunction<String, Iterable<String>> { sentence: String ->
+ sentence.split(" ")
+ })
+ )
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-info.yaml
new file mode 100644
index 0000000..59f135d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1755
+ length: 204
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-remote-info.yaml
new file mode 100644
index 0000000..97f4df9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326875
+update_date: Sun, 31 May 2020 13:45:16 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task.md b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task.md
new file mode 100644
index 0000000..8eb555c
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task.md
@@ -0,0 +1,39 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+FlatMapElements
+---------------
+
+The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.
+
+FlatMapElements can be used to simplify a DoFn that maps an element to multiple elements (one to
+many).
+
+**Kata:** Implement a function that maps each input sentence into words tokenized by whitespace
+(" ") using [FlatMapElements.into(...).via(...)](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/FlatMapElements.html).
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/FlatMapElements.html">
+ FlatMapElements.into(...).via(...)</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#lightweight-dofns">
+ "Lightweight DoFns and other abstractions"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt
new file mode 100644
index 0000000..efebb11
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.flatmapelements
+
+import org.apache.beam.learning.katas.coretransforms.map.flatmapelements.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_map_flatmapelements() {
+ val values = Create.of("Apache Beam", "Unified Batch and Streaming")
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(
+ "Apache", "Beam", "Unified", "Batch", "and", "Streaming"
+ )
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt b/learning/katas/kotlin/Core Transforms/Map/MapElements/src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt
new file mode 100644
index 0000000..5d040be
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.mapelements
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(10, 20, 30, 40, 50))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(
+ MapElements
+ .into(TypeDescriptors.integers())
+ .via(SerializableFunction { number: Int -> number * 5 })
+ )
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-info.yaml
new file mode 100644
index 0000000..384850b
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1711
+ length: 143
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-remote-info.yaml
new file mode 100644
index 0000000..6ba2aae
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326874
+update_date: Sun, 31 May 2020 13:43:53 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/task.md b/learning/katas/kotlin/Core Transforms/Map/MapElements/task.md
new file mode 100644
index 0000000..05b77f8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/task.md
@@ -0,0 +1,38 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+MapElements
+-----------
+
+The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.
+
+MapElements can be used to simplify a DoFn that maps an element to another element (one to one).
+
+**Kata:** Implement a simple map function that multiplies all input elements by 5 using
+[MapElements.into(...).via(...)](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/MapElements.html).
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/MapElements.html">
+ MapElements.into(...).via(...)</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#lightweight-dofns">
+ "Lightweight DoFns and other abstractions"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/MapElements/test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt
new file mode 100644
index 0000000..f97c3d1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.mapelements
+
+import org.apache.beam.learning.katas.coretransforms.map.mapelements.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_map_mapelements() {
+ val values = Create.of(10, 20, 30, 40, 50)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(50, 100, 150, 200, 250)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt
new file mode 100644
index 0000000..3784687
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardoonetomany
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val sentences = pipeline.apply(Create.of("Hello Beam", "It is awesome"))
+
+ val output = applyTransform(sentences)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<String>): PCollection<String> {
+ return input.apply(ParDo.of(object : DoFn<String, String>() {
+ @ProcessElement
+ fun processElement(@Element sentence: String, out: OutputReceiver<String?>) {
+ val words = sentence.split(" ")
+ for (word in words) {
+ out.output(word)
+ }
+ }
+ }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-info.yaml
new file mode 100644
index 0000000..e85d53d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1663
+ length: 283
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-remote-info.yaml
new file mode 100644
index 0000000..1fa612f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326914
+update_date: Sun, 31 May 2020 13:43:51 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task.md b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task.md
new file mode 100644
index 0000000..013ef1d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task.md
@@ -0,0 +1,37 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+ParDo OneToMany
+---------------
+
+**Kata:** Please write a ParDo that maps each input sentence into words tokenized by whitespace
+(" ").
+
+<div class="hint">
+ You can call <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.OutputReceiver.html">
+ OutputReceiver</a> multiple times in a
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo</a>.
+</div>
+
+<div class="hint">
+ If you're using Beam version before v2.5.0, you can call
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.WindowedContext.html#output-OutputT-">
+ DoFn.ProcessContext.output(..)</a> multiple times in a
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">ParDo</a>.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt
new file mode 100644
index 0000000..d890a91
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardoonetomany
+
+import org.apache.beam.learning.katas.coretransforms.map.pardoonetomany.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_map_pardo_onetomany() {
+ val values = Create.of("Hello Beam", "It is awesome")
+ val numbers = testPipeline.apply(values)
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder("Hello", "Beam", "It", "is", "awesome")
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo/src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt
new file mode 100644
index 0000000..f11df16
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardo
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5))
+
+ val output = applyTransform(numbers)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+ return input.apply(ParDo.of(object : DoFn<Int, Int>() {
+ @ProcessElement
+ fun processElement(context: ProcessContext, out: OutputReceiver<Int>) {
+ val number = context.element()
+ out.output(number * 10)
+ }
+ }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-info.yaml
new file mode 100644
index 0000000..8dd9409
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1629
+ length: 235
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-remote-info.yaml
new file mode 100644
index 0000000..15825c8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326916
+update_date: Sun, 31 May 2020 13:43:48 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/task.md b/learning/katas/kotlin/Core Transforms/Map/ParDo/task.md
new file mode 100644
index 0000000..bfcb16f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/task.md
@@ -0,0 +1,40 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+ParDo
+-----
+
+ParDo is a Beam transform for generic parallel processing. The ParDo processing paradigm is similar
+to the “Map” phase of a Map/Shuffle/Reduce-style algorithm: a ParDo transform considers each
+element in the input PCollection, performs some processing function (your user code) on that
+element, and emits zero, one, or multiple elements to an output PCollection.
+
+**Kata:** Please write a simple ParDo that maps the input element by multiplying it by 10.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo</a>
+ with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+ DoFn</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#pardo">"ParDo"</a> section for
+ more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo/test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt
new file mode 100644
index 0000000..9fbf7fd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardo
+
+import org.apache.beam.learning.katas.coretransforms.map.pardo.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_map_pardo() {
+ val values = Create.of(1, 2, 3, 4, 5)
+ val numbers = testPipeline.apply(values)
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results).containsInAnyOrder(10, 20, 30, 40, 50)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Map/lesson-info.yaml
new file mode 100644
index 0000000..ad6558f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/lesson-info.yaml
@@ -0,0 +1,24 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- ParDo
+- ParDo OneToMany
+- MapElements
+- FlatMapElements
diff --git a/learning/katas/kotlin/Core Transforms/Map/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/lesson-remote-info.yaml
new file mode 100644
index 0000000..9086cc1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358521
+update_date: Wed, 20 May 2020 20:27:14 UTC
+unit: 342722
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt b/learning/katas/kotlin/Core Transforms/Partition/Partition/src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt
new file mode 100644
index 0000000..a706565
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.partition
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Partition
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionList
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(
+ Create.of(1, 2, 3, 4, 5, 100, 110, 150, 250)
+ )
+
+ val partition = applyTransform(numbers)
+
+ partition[0].apply(Log.ofElements("Number > 100: "))
+ partition[1].apply(Log.ofElements("Number <= 100: "))
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<Int>): PCollectionList<Int> {
+ return input
+ .apply(Partition.of(2) { number: Int, numPartitions: Int ->
+ if (number > 100) {
+ 0
+ } else {
+ 1
+ }
+ })
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/task-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-info.yaml
new file mode 100644
index 0000000..000f725
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1758
+ length: 159
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-remote-info.yaml
new file mode 100644
index 0000000..2d0bcc1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326883
+update_date: Sat, 30 May 2020 18:50:11 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/task.md b/learning/katas/kotlin/Core Transforms/Partition/Partition/task.md
new file mode 100644
index 0000000..e254afd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/task.md
@@ -0,0 +1,44 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Partition
+---------
+
+Partition is a Beam transform for PCollection objects that store the same data type. Partition
+splits a single PCollection into a fixed number of smaller collections.
+
+Partition divides the elements of a PCollection according to a partitioning function that you
+provide. The partitioning function contains the logic that determines how to split up the elements
+of the input PCollection into each resulting partition PCollection.
+
+**Kata:** Implement a
+[Partition](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Partition.html)
+transform that splits a PCollection of numbers into two PCollections. The first PCollection
+contains numbers greater than 100, and the second PCollection contains the remaining numbers.
+
+<div class="hint">
+ Refer to
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Partition.html">
+ Partition</a> to solve this problem.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#partition">
+ "Partition"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Partition/Partition/test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt
new file mode 100644
index 0000000..2785c60
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.partition
+
+import org.apache.beam.learning.katas.coretransforms.partition.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_partition_partition() {
+ val numbers = testPipeline.apply(Create.of(1, 2, 3, 4, 5, 100, 110, 150, 250))
+
+ val results = applyTransform(numbers)
+
+ PAssert.that(results[0]).containsInAnyOrder(110, 150, 250)
+
+ PAssert.that(results[1]).containsInAnyOrder(1, 2, 3, 4, 5, 100)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Partition/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/lesson-info.yaml
new file mode 100644
index 0000000..c15773b
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Partition
diff --git a/learning/katas/kotlin/Core Transforms/Partition/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/lesson-remote-info.yaml
new file mode 100644
index 0000000..eb19f96
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358526
+update_date: Wed, 20 May 2020 20:27:52 UTC
+unit: 342727
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt
new file mode 100644
index 0000000..8e16b90
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideinput
+
+import java.io.Serializable
+
+data class Person(val name: String?, val city: String?, private val country: String? = null) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt
new file mode 100644
index 0000000..527ca2d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideinput
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.transforms.View
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionView
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val citiesToCountries = pipeline.apply(
+ "Cities and Countries",
+ Create.of(
+ KV.of("Beijing", "China"),
+ KV.of("London", "United Kingdom"),
+ KV.of("San Francisco", "United States"),
+ KV.of("Singapore", "Singapore"),
+ KV.of("Sydney", "Australia")
+ )
+ )
+
+ val citiesToCountriesView = createView(citiesToCountries)
+
+ val persons = pipeline.apply(
+ "Persons",
+ Create.of(
+ Person("Henry", "Singapore"),
+ Person("Jane", "San Francisco"),
+ Person("Lee", "Beijing"),
+ Person("John", "Sydney"),
+ Person("Alfred", "London")
+ )
+ )
+
+ val output = applyTransform(persons, citiesToCountriesView)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun createView(citiesToCountries: PCollection<KV<String, String>>): PCollectionView<Map<String, String>> {
+ return citiesToCountries.apply(View.asMap())
+ }
+
+ @JvmStatic
+ fun applyTransform(
+ persons: PCollection<Person>,
+ citiesToCountriesView: PCollectionView<Map<String, String>>
+ ): PCollection<Person> {
+
+ return persons.apply(ParDo.of(object : DoFn<Person, Person>() {
+ @ProcessElement
+ fun processElement(@Element person: Person, out: OutputReceiver<Person>, context: ProcessContext) {
+ val citiesToCountries: Map<String, String> = context.sideInput(citiesToCountriesView)
+ val city = person.city
+ val country = citiesToCountries[city]
+
+ out.output(Person(person.name, city, country))
+ }
+ }).withSideInputs(citiesToCountriesView))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/task.md b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/task.md
new file mode 100644
index 0000000..6ebde27
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/task.md
@@ -0,0 +1,52 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Side Input
+----------
+
+In addition to the main input PCollection, you can provide additional inputs to a ParDo transform
+in the form of side inputs. A side input is an additional input that your DoFn can access each time
+it processes an element in the input PCollection. When you specify a side input, you create a view
+of some other data that can be read from within the ParDo transform’s DoFn while processing each
+element.
+
+Side inputs are useful if your ParDo needs to inject additional data when processing each element
+in the input PCollection, but the additional data needs to be determined at runtime (and not
+hard-coded). Such values might be determined by the input data, or depend on a different branch of
+your pipeline.
+
+**Kata:** Please enrich each Person with the country based on the city he/she lives in.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/View.html">
+ View</a> to create PCollectionView of citiesToCountries.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo</a> with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+ DoFn</a> that accepts
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withSideInputs-org.apache.beam.sdk.values.PCollectionView...-">
+ side input</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#side-inputs">"Side inputs"</a>
+ section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-info.yaml
new file mode 100644
index 0000000..bdfed39
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-info.yaml
@@ -0,0 +1,34 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt
+ visible: true
+- name: src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt
+ visible: true
+ placeholders:
+ - offset: 2390
+ length: 37
+ placeholder_text: TODO()
+ - offset: 2605
+ length: 465
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-remote-info.yaml
new file mode 100644
index 0000000..897f640
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326884
+update_date: Sat, 30 May 2020 18:48:28 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task.md b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task.md
new file mode 100644
index 0000000..6ebde27
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task.md
@@ -0,0 +1,52 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Side Input
+----------
+
+In addition to the main input PCollection, you can provide additional inputs to a ParDo transform
+in the form of side inputs. A side input is an additional input that your DoFn can access each time
+it processes an element in the input PCollection. When you specify a side input, you create a view
+of some other data that can be read from within the ParDo transform’s DoFn while processing each
+element.
+
+Side inputs are useful if your ParDo needs to inject additional data when processing each element
+in the input PCollection, but the additional data needs to be determined at runtime (and not
+hard-coded). Such values might be determined by the input data, or depend on a different branch of
+your pipeline.
+
+**Kata:** Please enrich each Person with the country based on the city he/she lives in.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/View.html">
+ View</a> to create PCollectionView of citiesToCountries.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo</a> with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+ DoFn</a> that accepts
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withSideInputs-org.apache.beam.sdk.values.PCollectionView...-">
+ side input</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#side-inputs">"Side inputs"</a>
+ section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt
new file mode 100644
index 0000000..5b011e2
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideinput
+
+import org.apache.beam.learning.katas.coretransforms.sideinput.Task.applyTransform
+import org.apache.beam.learning.katas.coretransforms.sideinput.Task.createView
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_side_input_side_input() {
+ val citiesToCountries = testPipeline.apply(
+ "Cities and Countries",
+ Create.of(
+ KV.of("Beijing", "China"),
+ KV.of("London", "United Kingdom"),
+ KV.of("San Francisco", "United States"),
+ KV.of("Singapore", "Singapore"),
+ KV.of("Sydney", "Australia")
+ )
+ )
+
+ val citiesToCountriesView = createView(citiesToCountries)
+
+ val persons = testPipeline.apply(
+ "Persons",
+ Create.of(
+ Person("Henry", "Singapore"),
+ Person("Jane", "San Francisco"),
+ Person("Lee", "Beijing"),
+ Person("John", "Sydney"),
+ Person("Alfred", "London")
+ )
+ )
+
+ val results = applyTransform(persons, citiesToCountriesView)
+
+ PAssert.that(results).containsInAnyOrder(
+ Person("Henry", "Singapore", "Singapore"),
+ Person("Jane", "San Francisco", "United States"),
+ Person("Lee", "Beijing", "China"),
+ Person("John", "Sydney", "Australia"),
+ Person("Alfred", "London", "United Kingdom")
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/lesson-info.yaml
new file mode 100644
index 0000000..210e3b0
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Side Input
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/lesson-remote-info.yaml
new file mode 100644
index 0000000..f96f0bd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358527
+update_date: Wed, 20 May 2020 20:27:56 UTC
+unit: 342728
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt
new file mode 100644
index 0000000..659e218
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideoutput
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionTuple
+import org.apache.beam.sdk.values.TupleTag
+import org.apache.beam.sdk.values.TupleTagList
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val numbers = pipeline.apply(Create.of(10, 50, 120, 20, 200, 0))
+
+ val numBelow100Tag = object : TupleTag<Int>() {}
+ val numAbove100Tag = object : TupleTag<Int>() {}
+ val outputTuple = applyTransform(numbers, numBelow100Tag, numAbove100Tag)
+
+ outputTuple.get(numBelow100Tag).apply(Log.ofElements("Number <= 100: "))
+ outputTuple.get(numAbove100Tag).apply(Log.ofElements("Number > 100: "))
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(
+ numbers: PCollection<Int>,
+ numBelow100Tag: TupleTag<Int>,
+ numAbove100Tag: TupleTag<Int>
+ ): PCollectionTuple {
+
+ return numbers.apply(ParDo.of(object : DoFn<Int, Int>() {
+ @ProcessElement
+ fun processElement(context: ProcessContext, out: MultiOutputReceiver) {
+ val number = context.element()
+ if (number <= 100) {
+ out.get(numBelow100Tag).output(number)
+ } else {
+ out.get(numAbove100Tag).output(number)
+ }
+ }
+ }).withOutputTags(numBelow100Tag, TupleTagList.of(numAbove100Tag)))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/task.md b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/task.md
new file mode 100644
index 0000000..d690244
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/task.md
@@ -0,0 +1,42 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Side Output
+-----------
+
+While ParDo always produces a main output PCollection (as the return value from apply), you can
+also have your ParDo produce any number of additional output PCollections. If you choose to have
+multiple outputs, your ParDo returns all of the output PCollections (including the main output)
+bundled together.
+
+**Kata:** Implement additional output to your ParDo for numbers bigger than 100.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.MultiOutputReceiver.html">
+ MultiOutputReceiver</a> and
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withOutputTags-org.apache.beam.sdk.values.TupleTag-org.apache.beam.sdk.values.TupleTagList-">
+ .withOutputTags</a> to output multiple tagged-outputs in a
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo.</a>
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#additional-outputs">
+ "Additional outputs"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-info.yaml
new file mode 100644
index 0000000..d3d89c3
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt
+ visible: true
+ placeholders:
+ - offset: 2109
+ length: 423
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-remote-info.yaml
new file mode 100644
index 0000000..309a6c0
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326885
+update_date: Sat, 30 May 2020 18:48:30 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task.md b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task.md
new file mode 100644
index 0000000..d690244
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task.md
@@ -0,0 +1,42 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Side Output
+-----------
+
+While ParDo always produces a main output PCollection (as the return value from apply), you can
+also have your ParDo produce any number of additional output PCollections. If you choose to have
+multiple outputs, your ParDo returns all of the output PCollections (including the main output)
+bundled together.
+
+**Kata:** Implement additional output to your ParDo for numbers bigger than 100.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.MultiOutputReceiver.html">
+ MultiOutputReceiver</a> and
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withOutputTags-org.apache.beam.sdk.values.TupleTag-org.apache.beam.sdk.values.TupleTagList-">
+ .withOutputTags</a> to output multiple tagged-outputs in a
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo.</a>
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#additional-outputs">
+ "Additional outputs"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt
new file mode 100644
index 0000000..46afa1e
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideoutput
+
+import org.apache.beam.learning.katas.coretransforms.sideoutput.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.TupleTag
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun core_transforms_side_output_side_output() {
+ val numbers = testPipeline.apply(Create.of(10, 50, 120, 20, 200, 0))
+
+ val numBelow100Tag = object : TupleTag<Int>() {}
+ val numAbove100Tag = object : TupleTag<Int>() {}
+
+ val resultsTuple = applyTransform(numbers, numBelow100Tag, numAbove100Tag)
+
+ PAssert.that(resultsTuple.get(numBelow100Tag)).containsInAnyOrder(0, 10, 20, 50)
+
+ PAssert.that(resultsTuple.get(numAbove100Tag)).containsInAnyOrder(120, 200)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/lesson-info.yaml
new file mode 100644
index 0000000..e9096c9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Side Output
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/lesson-remote-info.yaml
new file mode 100644
index 0000000..b9af67a
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358528
+update_date: Wed, 20 May 2020 20:28:03 UTC
+unit: 342729
diff --git a/learning/katas/kotlin/Core Transforms/section-info.yaml b/learning/katas/kotlin/Core Transforms/section-info.yaml
new file mode 100644
index 0000000..7a9eda8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/section-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Map
+- GroupByKey
+- CoGroupByKey
+- Combine
+- Flatten
+- Partition
+- Side Input
+- Side Output
+- Branching
+- Composite Transform
+- DoFn Additional Parameters
diff --git a/learning/katas/kotlin/Core Transforms/section-remote-info.yaml b/learning/katas/kotlin/Core Transforms/section-remote-info.yaml
new file mode 100644
index 0000000..965b247
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133888
+update_date: Wed, 20 May 2020 20:27:13 UTC
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/src/org/apache/beam/learning/katas/examples/wordcount/Task.kt b/learning/katas/kotlin/Examples/Word Count/Word Count/src/org/apache/beam/learning/katas/examples/wordcount/Task.kt
new file mode 100644
index 0000000..67e2afc
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/src/org/apache/beam/learning/katas/examples/wordcount/Task.kt
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.examples.wordcount
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.*
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val lines = arrayOf(
+ "apple orange grape banana apple banana",
+ "banana orange banana papaya"
+ )
+
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val wordCounts = pipeline.apply(Create.of(listOf(*lines)))
+
+ val output = applyTransform(wordCounts)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<String>): PCollection<String> {
+ return input
+ .apply(
+ FlatMapElements
+ .into(TypeDescriptors.strings())
+ .via(SerializableFunction<String, Iterable<String>> { line: String ->
+ line.split(" ")
+ })
+ )
+ .apply(Count.perElement())
+ .apply(ParDo.of(object : DoFn<KV<String, Long>, String>() {
+ @ProcessElement
+ fun processElement(@Element element: KV<String, Long>, out: OutputReceiver<String>) {
+ out.output(element.key.toString() + ":" + element.value)
+ }
+ }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/task-info.yaml b/learning/katas/kotlin/Examples/Word Count/Word Count/task-info.yaml
new file mode 100644
index 0000000..8807028
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/examples/wordcount/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1733
+ length: 519
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/task-remote-info.yaml b/learning/katas/kotlin/Examples/Word Count/Word Count/task-remote-info.yaml
new file mode 100644
index 0000000..a70cf74
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326909
+update_date: Sat, 30 May 2020 18:49:17 UTC
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/task.md b/learning/katas/kotlin/Examples/Word Count/Word Count/task.md
new file mode 100644
index 0000000..d8dbdff
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/task.md
@@ -0,0 +1,33 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Word Count Pipeline
+-------------------
+
+**Kata:** Create a pipeline that counts the number of words.
+
+Please output the count of each word in the following format:
+```text
+word:count
+ball:5
+book:3
+```
+
+<div class="hint">
+ Refer to your katas above.
+</div>
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt b/learning/katas/kotlin/Examples/Word Count/Word Count/test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt
new file mode 100644
index 0000000..48858ba
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.examples.wordcount
+
+import org.apache.beam.learning.katas.examples.wordcount.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun examples_word_count_word_count() {
+ val lines = Create.of(
+ "apple orange grape banana apple banana",
+ "banana orange banana papaya"
+ )
+
+ val linesPColl = testPipeline.apply(lines)
+
+ val results = applyTransform(linesPColl)
+
+ PAssert.that(results).containsInAnyOrder(
+ "apple:2",
+ "banana:4",
+ "grape:1",
+ "orange:2",
+ "papaya:1"
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Examples/Word Count/lesson-info.yaml b/learning/katas/kotlin/Examples/Word Count/lesson-info.yaml
new file mode 100644
index 0000000..cbe1d6f
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Word Count
diff --git a/learning/katas/kotlin/Examples/Word Count/lesson-remote-info.yaml b/learning/katas/kotlin/Examples/Word Count/lesson-remote-info.yaml
new file mode 100644
index 0000000..649768a
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358542
+update_date: Wed, 20 May 2020 20:29:29 UTC
+unit: 342743
diff --git a/learning/katas/kotlin/Examples/section-info.yaml b/learning/katas/kotlin/Examples/section-info.yaml
new file mode 100644
index 0000000..cbe1d6f
--- /dev/null
+++ b/learning/katas/kotlin/Examples/section-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Word Count
diff --git a/learning/katas/kotlin/Examples/section-remote-info.yaml b/learning/katas/kotlin/Examples/section-remote-info.yaml
new file mode 100644
index 0000000..1dd0468
--- /dev/null
+++ b/learning/katas/kotlin/Examples/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133893
+update_date: Wed, 20 May 2020 20:29:28 UTC
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/src/org/apache/beam/learning/katas/io/builtinios/Task.kt b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/src/org/apache/beam/learning/katas/io/builtinios/Task.kt
new file mode 100644
index 0000000..42e5b4b
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/src/org/apache/beam/learning/katas/io/builtinios/Task.kt
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.builtinios
+
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ pipeline.run()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-info.yaml
new file mode 100644
index 0000000..c684624
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-info.yaml
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: theory
+files:
+- name: src/org/apache/beam/learning/katas/io/builtinios/Task.kt
+ visible: true
+- name: test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-remote-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-remote-info.yaml
new file mode 100644
index 0000000..6148789
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326902
+update_date: Sat, 30 May 2020 18:49:02 UTC
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task.md b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task.md
new file mode 100644
index 0000000..b083c73
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task.md
@@ -0,0 +1,29 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Built-in I/Os
+-------------
+
+Beam SDKs provide many out of the box I/O transforms that can be used to read from many different
+sources and write to many different sinks.
+
+See the [Beam-provided I/O Transforms](https://beam.apache.org/documentation/io/built-in/) page for
+a list of the currently available I/O transforms.
+
+**Note:** There is no kata for this task. Please click the "Check" button and proceed to the next
+task.
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt
new file mode 100644
index 0000000..68ef12c
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.builtinios
+
+class TaskTest
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/Built-in IOs/lesson-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/lesson-info.yaml
new file mode 100644
index 0000000..af969f1
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Built-in IOs
diff --git a/learning/katas/kotlin/IO/Built-in IOs/lesson-remote-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/lesson-remote-info.yaml
new file mode 100644
index 0000000..22f4247
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358536
+update_date: Wed, 20 May 2020 20:28:54 UTC
+unit: 342737
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/countries.txt b/learning/katas/kotlin/IO/TextIO/TextIO Read/countries.txt
new file mode 100644
index 0000000..9d6848f
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/countries.txt
@@ -0,0 +1,10 @@
+Singapore
+United States
+Australia
+England
+France
+China
+Indonesia
+Mexico
+Germany
+Japan
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/src/org/apache/beam/learning/katas/io/textio/read/Task.kt b/learning/katas/kotlin/IO/TextIO/TextIO Read/src/org/apache/beam/learning/katas/io/textio/read/Task.kt
new file mode 100644
index 0000000..69a499c
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/src/org/apache/beam/learning/katas/io/textio/read/Task.kt
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.textio.read
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.io.TextIO
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+ private const val FILE_PATH = "IO/TextIO/TextIO Read/countries.txt"
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val countries = pipeline.apply("Read Countries", TextIO.read().from(FILE_PATH))
+
+ val output = applyTransform(countries)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(input: PCollection<String>): PCollection<String> {
+ return input.apply(
+ MapElements
+ .into(TypeDescriptors.strings())
+ .via(SerializableFunction(String::toUpperCase))
+ )
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/task-info.yaml b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-info.yaml
new file mode 100644
index 0000000..92d392f
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-info.yaml
@@ -0,0 +1,34 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: countries.txt
+ visible: true
+- name: src/org/apache/beam/learning/katas/io/textio/read/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1541
+ length: 29
+ placeholder_text: TODO()
+ - offset: 1773
+ length: 133
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/task-remote-info.yaml b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-remote-info.yaml
new file mode 100644
index 0000000..1c29b22
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326901
+update_date: Sat, 30 May 2020 18:50:19 UTC
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/task.md b/learning/katas/kotlin/IO/TextIO/TextIO Read/task.md
new file mode 100644
index 0000000..23dd394
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/task.md
@@ -0,0 +1,44 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+TextIO Read
+-----------
+
+When you create a pipeline, you often need to read data from some external source, such as a file
+or a database. Likewise, you may want your pipeline to output its result data to an external
+storage system. Beam provides read and write transforms for a number of common data storage types.
+If you want your pipeline to read from or write to a data storage format that isn’t supported by
+the built-in transforms, you can implement your own read and write transforms.
+
+To read a PCollection from one or more text files, use TextIO.read() to instantiate a transform
+and use TextIO.Read.from(String) to specify the path of the file(s) to be read.
+
+**Kata:** Read the 'countries.txt' file and convert each country name into uppercase.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/io/TextIO.html">
+ TextIO</a> and its corresponding
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/io/TextIO.html#read--">
+ TextIO.read()</a> method.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#pipeline-io-reading-data">
+ "Reading input data"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt b/learning/katas/kotlin/IO/TextIO/TextIO Read/test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt
new file mode 100644
index 0000000..62bb832
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.textio.read
+
+import org.apache.beam.learning.katas.io.textio.read.Task.applyTransform
+import org.apache.beam.sdk.io.TextIO
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun io_textio_textio_read() {
+ val countries = testPipeline.apply(TextIO.read().from("countries.txt"))
+
+ val results = applyTransform(countries)
+
+ PAssert.that(results).containsInAnyOrder(
+ "AUSTRALIA",
+ "CHINA",
+ "ENGLAND",
+ "FRANCE",
+ "GERMANY",
+ "INDONESIA",
+ "JAPAN",
+ "MEXICO",
+ "SINGAPORE",
+ "UNITED STATES"
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/TextIO/lesson-info.yaml b/learning/katas/kotlin/IO/TextIO/lesson-info.yaml
new file mode 100644
index 0000000..e671ddc
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- TextIO Read
diff --git a/learning/katas/kotlin/IO/TextIO/lesson-remote-info.yaml b/learning/katas/kotlin/IO/TextIO/lesson-remote-info.yaml
new file mode 100644
index 0000000..d8716cb
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358535
+update_date: Wed, 20 May 2020 20:28:49 UTC
+unit: 342736
diff --git a/learning/katas/kotlin/IO/section-info.yaml b/learning/katas/kotlin/IO/section-info.yaml
new file mode 100644
index 0000000..1d93752
--- /dev/null
+++ b/learning/katas/kotlin/IO/section-info.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- TextIO
+- Built-in IOs
diff --git a/learning/katas/kotlin/IO/section-remote-info.yaml b/learning/katas/kotlin/IO/section-remote-info.yaml
new file mode 100644
index 0000000..d299c8a
--- /dev/null
+++ b/learning/katas/kotlin/IO/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133890
+update_date: Wed, 20 May 2020 20:28:48 UTC
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/src/org/apache/beam/learning/katas/intro/hello/Task.kt b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/src/org/apache/beam/learning/katas/intro/hello/Task.kt
new file mode 100644
index 0000000..857b663
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/src/org/apache/beam/learning/katas/intro/hello/Task.kt
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.intro.hello
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val output = setupPipeline(pipeline)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun setupPipeline(pipeline: Pipeline): PCollection<String> {
+ return pipeline.apply(Create.of("Hello Beam"))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-info.yaml
new file mode 100644
index 0000000..d2d8f64
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-info.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/intro/hello/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1465
+ length: 39
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-remote-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-remote-info.yaml
new file mode 100644
index 0000000..32361a0
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326913
+update_date: Sat, 30 May 2020 18:48:01 UTC
diff --git a/learning/katas/java/Introduction/Hello Beam/Hello Beam/task.md b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task.md
similarity index 100%
rename from learning/katas/java/Introduction/Hello Beam/Hello Beam/task.md
rename to learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task.md
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt
new file mode 100644
index 0000000..dff0346
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.intro.hello
+
+import org.apache.beam.learning.katas.intro.hello.Task.setupPipeline
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun introduction_hello_beam_hello_beam() {
+ val results = setupPipeline(testPipeline)
+
+ PAssert.that(results).containsInAnyOrder("Hello Beam")
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/lesson-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/lesson-info.yaml
new file mode 100644
index 0000000..040e0ac
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Hello Beam
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/lesson-remote-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/lesson-remote-info.yaml
new file mode 100644
index 0000000..b2b8037
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358520
+update_date: Wed, 20 May 2020 20:27:07 UTC
+unit: 342721
diff --git a/learning/katas/kotlin/Introduction/section-info.yaml b/learning/katas/kotlin/Introduction/section-info.yaml
new file mode 100644
index 0000000..040e0ac
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/section-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Hello Beam
diff --git a/learning/katas/kotlin/Introduction/section-remote-info.yaml b/learning/katas/kotlin/Introduction/section-remote-info.yaml
new file mode 100644
index 0000000..8c26adf
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133887
+update_date: Wed, 20 May 2020 20:27:05 UTC
diff --git a/learning/katas/kotlin/README.md b/learning/katas/kotlin/README.md
new file mode 100644
index 0000000..5343cc6
--- /dev/null
+++ b/learning/katas/kotlin/README.md
@@ -0,0 +1,31 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+### How to Setup
+Please follow the below steps in order to setup the project properly:
+* Using IntelliJ Education (or IntelliJ with EduTools plugin), select "Open" and select this
+directory (learning/katas/kotlin)
+* "Import Gradle project" when prompted, and configure the Gradle setup
+* Wait for Gradle build to finish
+* Open "Project Structure" and setup the project SDK (e.g. JDK 8)
+* Open the "Project" tool window, and select the "Course" view
+* Your project is ready
+
+For further instructions on how the IntelliJ Education works, you can refer
+[here](https://www.jetbrains.com/help/education/educator-start-guide.html?section=Kotlin).
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt
new file mode 100644
index 0000000..ab49dc0
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.earlytriggers
+
+import org.apache.beam.sdk.io.GenerateSequence
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.PTransform
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PBegin
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import org.joda.time.Duration
+
+class GenerateEvent : PTransform<PBegin, PCollection<String>>() {
+ companion object {
+ fun everySecond(): GenerateEvent {
+ return GenerateEvent()
+ }
+ }
+
+ override fun expand(input: PBegin): PCollection<String> {
+ return input
+ .apply(GenerateSequence.from(1).withRate(1, Duration.standardSeconds(1)))
+ .apply(MapElements.into(TypeDescriptors.strings()).via(SerializableFunction { "event" }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt
new file mode 100644
index 0000000..df427e6
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.earlytriggers
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.windowing.AfterProcessingTime
+import org.apache.beam.sdk.transforms.windowing.AfterWatermark
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.Duration
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val events = pipeline.apply(GenerateEvent.everySecond())
+
+ val output = applyTransform(events)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(events: PCollection<String>): PCollection<Long> {
+ return events
+ .apply(
+ Window.into<String>(FixedWindows.of(Duration.standardDays(1)))
+ .triggering(
+ AfterWatermark
+ .pastEndOfWindow()
+ .withEarlyFirings(AfterProcessingTime.pastFirstElementInPane())
+ )
+ .withAllowedLateness(Duration.ZERO)
+ .discardingFiredPanes()
+ )
+ .apply(Combine.globally(Count.combineFn<String>()).withoutDefaults())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-info.yaml
new file mode 100644
index 0000000..fcccec6
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt
+ visible: true
+- name: src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1854
+ length: 428
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-remote-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-remote-info.yaml
new file mode 100644
index 0000000..6b5bc11
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326907
+update_date: Sat, 30 May 2020 18:49:13 UTC
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task.md b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task.md
new file mode 100644
index 0000000..12d579f
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task.md
@@ -0,0 +1,60 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Early Triggers
+--------------
+
+Triggers allow Beam to emit early results, before all the data in a given window has arrived. For
+example, emitting after a certain amount of time elapses, or after a certain number of elements
+arrives.
+
+**Kata:** Given that events are being generated every second and a fixed window of 1-day duration,
+please implement an early trigger that emits the number of events count immediately after new
+element is processed.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.AfterWatermarkEarlyAndLate.html#withEarlyFirings-org.apache.beam.sdk.transforms.windowing.Trigger.OnceTrigger-">
+ withEarlyFirings</a> to set early firing triggers.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+ FixedWindows</a> with 1-day duration using
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.html#pastEndOfWindow--">
+ AfterWatermark.pastEndOfWindow()</a> trigger.
+</div>
+
+<div class="hint">
+ Set the <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#withAllowedLateness-org.joda.time.Duration-">
+ allowed lateness</a> to 0 with
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#discardingFiredPanes--">
+ discarding accumulation mode</a>.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.html#globally-org.apache.beam.sdk.transforms.CombineFnBase.GlobalCombineFn-">
+ Combine.globally</a> and
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html#combineFn--">
+ Count.combineFn</a> to calculate the count of events.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#event-time-triggers">
+ "Event time triggers"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt
new file mode 100644
index 0000000..8f6e527
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.earlytriggers
+
+import org.apache.beam.learning.katas.triggers.earlytriggers.Task.applyTransform
+import org.apache.beam.sdk.coders.SerializableCoder
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.testing.TestStream
+import org.apache.beam.sdk.transforms.windowing.IntervalWindow
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Duration
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun triggers_early_triggers_early_triggers() {
+ val testStream = TestStream.create(SerializableCoder.of(String::class.java))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(0)))
+ .advanceProcessingTime(Duration.standardSeconds(1))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(1)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(2)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(3)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(4)))
+ .advanceProcessingTime(Duration.standardSeconds(1))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(5)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(6)))
+ .advanceWatermarkToInfinity()
+
+ val eventsPColl = testPipeline.apply(testStream)
+
+ val results = applyTransform(eventsPColl)
+
+ PAssert.that(results)
+ .inEarlyPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+ .containsInAnyOrder(1L, 4L)
+ .inFinalPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+ .containsInAnyOrder(2L)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/lesson-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/lesson-info.yaml
new file mode 100644
index 0000000..184f82e
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Early Triggers
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/lesson-remote-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/lesson-remote-info.yaml
new file mode 100644
index 0000000..2a41ac1
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358540
+update_date: Wed, 20 May 2020 20:29:18 UTC
+unit: 342741
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt
new file mode 100644
index 0000000..617df70
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.eventtimetriggers
+
+import org.apache.beam.sdk.io.GenerateSequence
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.PTransform
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PBegin
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import org.joda.time.Duration
+
+class GenerateEvent : PTransform<PBegin, PCollection<String>>() {
+ companion object {
+ fun everySecond(): GenerateEvent {
+ return GenerateEvent()
+ }
+ }
+
+ override fun expand(input: PBegin): PCollection<String> {
+ return input
+ .apply(GenerateSequence.from(1).withRate(1, Duration.standardSeconds(1)))
+ .apply(MapElements.into(TypeDescriptors.strings()).via(SerializableFunction { "event" }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt
new file mode 100644
index 0000000..587448c
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.eventtimetriggers
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.windowing.AfterWatermark
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.Duration
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val events = pipeline.apply(GenerateEvent.everySecond())
+
+ val output = applyTransform(events)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(events: PCollection<String>): PCollection<Long> {
+ return events
+ .apply(
+ Window.into<String>(FixedWindows.of(Duration.standardSeconds(5)))
+ .triggering(AfterWatermark.pastEndOfWindow())
+ .withAllowedLateness(Duration.ZERO)
+ .discardingFiredPanes()
+ )
+ .apply(Combine.globally(Count.combineFn<String>()).withoutDefaults())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-info.yaml
new file mode 100644
index 0000000..c56d17c
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt
+ visible: true
+- name: src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1790
+ length: 314
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-remote-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-remote-info.yaml
new file mode 100644
index 0000000..4429fbd
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326906
+update_date: Sat, 30 May 2020 18:49:10 UTC
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task.md b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task.md
new file mode 100644
index 0000000..273ac8f
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task.md
@@ -0,0 +1,72 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Event Time Triggers
+-------------------
+
+When collecting and grouping data into windows, Beam uses triggers to determine when to emit the
+aggregated results of each window (referred to as a pane). If you use Beam’s default windowing
+configuration and default trigger, Beam outputs the aggregated result when it estimates all data
+has arrived, and discards all subsequent data for that window.
+
+You can set triggers for your PCollections to change this default behavior. Beam provides a number
+of pre-built triggers that you can set:
+
+* Event time triggers
+* Processing time triggers
+* Data-driven triggers
+* Composite triggers
+
+Event time triggers operate on the event time, as indicated by the timestamp on each data element.
+Beam’s default trigger is event time-based.
+
+The AfterWatermark trigger operates on event time. The AfterWatermark trigger emits the contents
+of a window after the watermark passes the end of the window, based on the timestamps attached to
+the data elements. The watermark is a global progress metric, and is Beam’s notion of input
+completeness within your pipeline at any given point. AfterWatermark.pastEndOfWindow() only fires
+when the watermark passes the end of the window.
+
+**Kata:** Given that events are being generated every second, please implement a trigger that emits
+the number of events count within a fixed window of 5-second duration.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+ FixedWindows</a> with 5-second duration using
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.html#pastEndOfWindow--">
+ AfterWatermark.pastEndOfWindow()</a> trigger.
+</div>
+
+<div class="hint">
+ Set the <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#withAllowedLateness-org.joda.time.Duration-">
+ allowed lateness</a> to 0 with
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#discardingFiredPanes--">
+ discarding accumulation mode</a>.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.html#globally-org.apache.beam.sdk.transforms.CombineFnBase.GlobalCombineFn-">
+ Combine.globally</a> and
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html#combineFn--">
+ Count.combineFn</a> to calculate the count of events.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#event-time-triggers">
+ "Event time triggers"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt
new file mode 100644
index 0000000..23f9ae5
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.eventtimetriggers
+
+import org.apache.beam.learning.katas.triggers.eventtimetriggers.Task.applyTransform
+import org.apache.beam.sdk.coders.SerializableCoder
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.testing.TestStream
+import org.apache.beam.sdk.transforms.windowing.IntervalWindow
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun triggers_event_time_triggers_event_time_triggers() {
+ val testStream = TestStream.create(SerializableCoder.of(String::class.java))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:01+00:00")))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:02+00:00")))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:03+00:00")))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:04+00:00")))
+ .advanceWatermarkTo(Instant.parse("2019-06-01T00:00:05+00:00"))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:05+00:00")))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:06+00:00")))
+ .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:07+00:00")))
+ .advanceWatermarkTo(Instant.parse("2019-06-01T00:00:10+00:00"))
+ .advanceWatermarkToInfinity()
+
+ val eventsPColl = testPipeline.apply(testStream)
+
+ val results = applyTransform(eventsPColl)
+
+ PAssert.that(results)
+ .inWindow(createIntervalWindow("2019-06-01T00:00:00+00:00", "2019-06-01T00:00:05+00:00"))
+ .containsInAnyOrder(5L)
+ .inWindow(createIntervalWindow("2019-06-01T00:00:05+00:00", "2019-06-01T00:00:10+00:00"))
+ .containsInAnyOrder(3L)
+
+ testPipeline.run().waitUntilFinish()
+ }
+
+ private fun createIntervalWindow(startStr: String, endStr: String): IntervalWindow {
+ return IntervalWindow(Instant.parse(startStr), Instant.parse(endStr))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-info.yaml
new file mode 100644
index 0000000..e423635
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Event Time Triggers
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-remote-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-remote-info.yaml
new file mode 100644
index 0000000..cac0151
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358539
+update_date: Wed, 20 May 2020 20:29:13 UTC
+unit: 342740
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt
new file mode 100644
index 0000000..5288a4f
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.windowaccummode
+
+import org.apache.beam.sdk.io.GenerateSequence
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.PTransform
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PBegin
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import org.joda.time.Duration
+
+class GenerateEvent : PTransform<PBegin, PCollection<String>>() {
+ companion object {
+ fun everySecond(): GenerateEvent {
+ return GenerateEvent()
+ }
+ }
+
+ override fun expand(input: PBegin): PCollection<String> {
+ return input
+ .apply(GenerateSequence.from(1).withRate(1, Duration.standardSeconds(1)))
+ .apply(MapElements.into(TypeDescriptors.strings()).via(SerializableFunction { "event" }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt
new file mode 100644
index 0000000..db3bf68
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.windowaccummode
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.windowing.AfterProcessingTime
+import org.apache.beam.sdk.transforms.windowing.AfterWatermark
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.Duration
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val events = pipeline.apply(GenerateEvent.everySecond())
+
+ val output = applyTransform(events)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(events: PCollection<String>): PCollection<Long> {
+ return events
+ .apply(
+ Window.into<String>(FixedWindows.of(Duration.standardDays(1)))
+ .triggering(
+ AfterWatermark
+ .pastEndOfWindow()
+ .withEarlyFirings(AfterProcessingTime.pastFirstElementInPane())
+ )
+ .withAllowedLateness(Duration.ZERO)
+ .accumulatingFiredPanes()
+ )
+ .apply(Combine.globally(Count.combineFn<String>()).withoutDefaults())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-info.yaml
new file mode 100644
index 0000000..89b48d1
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt
+ visible: true
+- name: src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt
+ visible: true
+ placeholders:
+ - offset: 1856
+ length: 430
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-remote-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-remote-info.yaml
new file mode 100644
index 0000000..8be1ca3
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326908
+update_date: Sat, 30 May 2020 18:49:15 UTC
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task.md b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task.md
new file mode 100644
index 0000000..90f4486
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task.md
@@ -0,0 +1,65 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Window Accumulation Mode
+------------------------
+
+When you specify a trigger, you must also set the the window’s accumulation mode. When a trigger
+fires, it emits the current contents of the window as a pane. Since a trigger can fire multiple
+times, the accumulation mode determines whether the system accumulates the window panes as the
+trigger fires, or discards them.
+
+**Kata:** Given that events are being generated every second and a fixed window of 1-day duration,
+please implement an early trigger that emits the number of events count immediately after new
+element is processed in accumulating mode.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/2.13.0/org/apache/beam/sdk/transforms/windowing/Window.html#accumulatingFiredPanes--">
+ accumulatingFiredPanes()</a> to set a window to accumulate the panes that are produced when the
+ trigger fires.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.AfterWatermarkEarlyAndLate.html#withEarlyFirings-org.apache.beam.sdk.transforms.windowing.Trigger.OnceTrigger-">
+ withEarlyFirings</a> to set early firing triggers.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+ FixedWindows</a> with 1-day duration using
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.html#pastEndOfWindow--">
+ AfterWatermark.pastEndOfWindow()</a> trigger.
+</div>
+
+<div class="hint">
+ Set the <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#withAllowedLateness-org.joda.time.Duration-">
+ allowed lateness</a> to 0.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.html#globally-org.apache.beam.sdk.transforms.CombineFnBase.GlobalCombineFn-">
+ Combine.globally</a> and
+ <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html#combineFn--">
+ Count.combineFn</a> to calculate the count of events.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#event-time-triggers">
+ "Event time triggers"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt
new file mode 100644
index 0000000..7e06c36
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.windowaccummode
+
+import org.apache.beam.learning.katas.triggers.windowaccummode.Task.applyTransform
+import org.apache.beam.sdk.coders.SerializableCoder
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.testing.TestStream
+import org.apache.beam.sdk.transforms.windowing.IntervalWindow
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Duration
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun triggers_window_accumulation_mode_window_accumulation_mode() {
+ val testStream = TestStream.create(SerializableCoder.of(String::class.java))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(0)))
+ .advanceProcessingTime(Duration.standardSeconds(1))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(1)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(2)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(3)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(4)))
+ .advanceProcessingTime(Duration.standardSeconds(1))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(5)))
+ .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(6)))
+ .advanceWatermarkToInfinity()
+
+ val eventsPColl = testPipeline.apply(testStream)
+
+ val results = applyTransform(eventsPColl)
+
+ PAssert.that(results)
+ .inEarlyPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+ .containsInAnyOrder(1L, 5L)
+ .inFinalPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+ .containsInAnyOrder(7L)
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-info.yaml
new file mode 100644
index 0000000..8a260af
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Window Accumulation Mode
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-remote-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-remote-info.yaml
new file mode 100644
index 0000000..9d9fa65
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358541
+update_date: Wed, 20 May 2020 20:29:23 UTC
+unit: 342742
diff --git a/learning/katas/kotlin/Triggers/section-info.yaml b/learning/katas/kotlin/Triggers/section-info.yaml
new file mode 100644
index 0000000..f62f316
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/section-info.yaml
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Event Time Triggers
+- Early Triggers
+- Window Accumulation Mode
diff --git a/learning/katas/kotlin/Triggers/section-remote-info.yaml b/learning/katas/kotlin/Triggers/section-remote-info.yaml
new file mode 100644
index 0000000..1e0f31d
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133892
+update_date: Wed, 20 May 2020 20:29:12 UTC
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt
new file mode 100644
index 0000000..03d79e1
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.pardo
+
+import org.joda.time.DateTime
+import java.io.Serializable
+
+data class Event(private var id: String, private var event: String, var date: DateTime) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt
new file mode 100644
index 0000000..7e73d95
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.pardo
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.DateTime
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val events = pipeline.apply(
+ Create.of(
+ Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+ Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+ Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+ Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+ Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+ )
+ )
+
+ val output = applyTransform(events)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(events: PCollection<Event>): PCollection<Event> {
+ return events.apply(ParDo.of(object : DoFn<Event, Event>() {
+ @ProcessElement
+ fun processElement(@Element event: Event, out: OutputReceiver<Event>) {
+ out.outputWithTimestamp(event, event.date.toInstant())
+ }
+ }))
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-info.yaml
new file mode 100644
index 0000000..5814cab
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt
+ visible: true
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt
+ visible: true
+ placeholders:
+ - offset: 2060
+ length: 232
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-remote-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-remote-info.yaml
new file mode 100644
index 0000000..eff63cb
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326903
+update_date: Sat, 30 May 2020 18:49:04 UTC
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task.md b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task.md
new file mode 100644
index 0000000..2da4912
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task.md
@@ -0,0 +1,46 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Adding Timestamp - ParDo
+------------------------
+
+Bounded sources (such as a file from TextIO) do not provide timestamps for elements. If you need
+timestamps, you must add them to your PCollection’s elements.
+
+You can assign new timestamps to the elements of a PCollection by applying a ParDo transform that
+outputs new elements with timestamps that you set.
+
+**Kata:** Please assign each element a timestamp based on the the `Event.date`.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+ ParDo</a>
+ with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+ DoFn</a>.
+</div>
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.OutputReceiver.html#outputWithTimestamp-T-org.joda.time.Instant-">
+ OutputReceiver.outputWithTimestamp</a> method to assign timestamp to the element.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#adding-timestamps-to-a-pcollections-elements">
+ "Adding timestamps to a PCollection’s elements"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt
new file mode 100644
index 0000000..2386ca5
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.pardo
+
+import org.apache.beam.learning.katas.windowing.addingtimestamp.pardo.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.KV
+import org.joda.time.DateTime
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun windowing_adding_timestamp_pardo() {
+ val events = listOf(
+ Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+ Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+ Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+ Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+ Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+ )
+
+ val eventsPColl = testPipeline.apply(Create.of(events))
+
+ val results = applyTransform(eventsPColl)
+
+ val timestampedResults = results.apply(
+ "KV<Event, Instant>",
+ ParDo.of(object : DoFn<Event, KV<Event, Instant>>() {
+
+ @ProcessElement
+ fun processElement(context: ProcessContext, out: OutputReceiver<KV<Event, Instant>>) {
+ val event = context.element()
+ out.output(KV.of(event, context.timestamp()))
+ }
+
+ })
+ )
+
+ PAssert.that(results).containsInAnyOrder(events)
+
+ PAssert.that(timestampedResults).containsInAnyOrder(
+ KV.of(events[0], events[0].date.toInstant()),
+ KV.of(events[1], events[1].date.toInstant()),
+ KV.of(events[2], events[2].date.toInstant()),
+ KV.of(events[3], events[3].date.toInstant()),
+ KV.of(events[4], events[4].date.toInstant())
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt
new file mode 100644
index 0000000..2016f1f
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps
+
+import org.joda.time.DateTime
+import java.io.Serializable
+
+data class Event(private var id: String, private var event: String, var date: DateTime) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt
new file mode 100644
index 0000000..40ccb2d
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.WithTimestamps
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.DateTime
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val events = pipeline.apply(
+ Create.of(
+ Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+ Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+ Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+ Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+ Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+ )
+ )
+
+ val output = applyTransform(events)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ @JvmStatic
+ fun applyTransform(events: PCollection<Event>): PCollection<Event> {
+ return events.apply(WithTimestamps.of { event: Event -> event.date.toInstant() })
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-info.yaml
new file mode 100644
index 0000000..058c723
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt
+ visible: true
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt
+ visible: true
+ placeholders:
+ - offset: 2035
+ length: 74
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt
+ visible: false
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-remote-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-remote-info.yaml
new file mode 100644
index 0000000..a34be18
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326904
+update_date: Sat, 30 May 2020 18:50:21 UTC
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task.md b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task.md
new file mode 100644
index 0000000..d5616e5
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task.md
@@ -0,0 +1,39 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Adding Timestamp - WithTimestamps
+---------------------------------
+
+Bounded sources (such as a file from TextIO) do not provide timestamps for elements. If you need
+timestamps, you must add them to your PCollection’s elements.
+
+You can assign new timestamps to the elements of a PCollection by applying a ParDo transform that
+outputs new elements with timestamps that you set.
+
+**Kata:** Please assign each element a timestamp based on the the `Event.date`.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/WithTimestamps.html">
+ WithTimestamps</a>.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#adding-timestamps-to-a-pcollections-elements">
+ "Adding timestamps to a PCollection’s elements"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt
new file mode 100644
index 0000000..ade7966
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps
+
+import org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.KV
+import org.joda.time.DateTime
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun windowing_adding_timestamp_withtimestamps() {
+ val events = listOf(
+ Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+ Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+ Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+ Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+ Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+ )
+
+ val eventsPColl = testPipeline.apply(Create.of(events))
+
+ val results = applyTransform(eventsPColl)
+
+ val timestampedResults = results.apply(
+ "KV<Event, Instant>",
+ ParDo.of(object : DoFn<Event, KV<Event, Instant>>() {
+ @ProcessElement
+ fun processElement(context: ProcessContext, out: OutputReceiver<KV<Event, Instant>>) {
+ val event = context.element()
+ out.output(KV.of(event, context.timestamp()))
+ }
+ })
+ )
+
+ PAssert.that(results).containsInAnyOrder(events)
+
+ PAssert.that(timestampedResults).containsInAnyOrder(
+ KV.of(events[0], events[0].date.toInstant()),
+ KV.of(events[1], events[1].date.toInstant()),
+ KV.of(events[2], events[2].date.toInstant()),
+ KV.of(events[3], events[3].date.toInstant()),
+ KV.of(events[4], events[4].date.toInstant())
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-info.yaml
new file mode 100644
index 0000000..c6a234c
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-info.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- ParDo
+- WithTimestamps
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-remote-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-remote-info.yaml
new file mode 100644
index 0000000..752baef
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358537
+update_date: Wed, 20 May 2020 20:29:00 UTC
+unit: 342738
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt
new file mode 100644
index 0000000..c56605d
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.fixedwindow
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Duration
+import org.joda.time.Instant
+
+object Task {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val options = PipelineOptionsFactory.fromArgs(*args).create()
+ val pipeline = Pipeline.create(options)
+
+ val events = pipeline.apply(
+ Create.timestamped(
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-10T00:00:00+00:00"))
+ )
+ )
+
+ val output = applyTransform(events)
+
+ output.apply(Log.ofElements())
+
+ pipeline.run()
+ }
+
+ fun applyTransform(events: PCollection<String>): PCollection<KV<String, Long>> {
+ return events
+ .apply(Window.into<String>(FixedWindows.of(Duration.standardDays(1))))
+ .apply(Count.perElement())
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-info.yaml
new file mode 100644
index 0000000..02deae9
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-info.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt
+ visible: true
+ placeholders:
+ - offset: 2668
+ length: 116
+ placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt
+ visible: false
+- name: test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt
+ visible: false
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-remote-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-remote-info.yaml
new file mode 100644
index 0000000..16d8396
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 1326905
+update_date: Sat, 30 May 2020 18:49:07 UTC
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task.md b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task.md
new file mode 100644
index 0000000..ff4c19c
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task.md
@@ -0,0 +1,53 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+Fixed Time Window
+-----------------
+
+Windowing subdivides a PCollection according to the timestamps of its individual elements.
+Transforms that aggregate multiple elements, such as GroupByKey and Combine, work implicitly on a
+per-window basis — they process each PCollection as a succession of multiple, finite windows,
+though the entire collection itself may be of unbounded size.
+
+In the Beam model, any PCollection (including unbounded PCollections) can be subdivided into
+logical windows. Each element in a PCollection is assigned to one or more windows according to the
+PCollection’s windowing function, and each individual window contains a finite number of elements.
+Grouping transforms then consider each PCollection’s elements on a per-window basis. GroupByKey,
+for example, implicitly groups the elements of a PCollection by key and window.
+
+Beam provides several windowing functions, including:
+* Fixed Time Windows
+* Sliding Time Windows
+* Per-Session Windows
+* Single Global Window
+
+The simplest form of windowing is using fixed time windows. A fixed time window represents a
+consistent duration, non overlapping time interval in the data stream.
+
+**Kata:** Please count the number of events that happened based on fixed window with 1-day duration.
+
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+ FixedWindows</a> with 1-day duration.
+</div>
+
+<div class="hint">
+ Refer to the Beam Programming Guide
+ <a href="https://beam.apache.org/documentation/programming-guide/#fixed-time-windows">
+ "Fixed time windows"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt
new file mode 100644
index 0000000..569c491
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.fixedwindow
+
+import org.apache.beam.learning.katas.windowing.fixedwindow.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.transforms.windowing.BoundedWindow
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+ @get:Rule
+ @Transient
+ val testPipeline: TestPipeline = TestPipeline.create()
+
+ @Test
+ fun windowing_fixed_window_time_fixed_window_time() {
+ val eventsPColl = testPipeline.apply(
+ Create.timestamped(
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+ TimestampedValue.of("event", Instant.parse("2019-06-10T00:00:00+00:00"))
+ )
+ )
+
+ val results = applyTransform(eventsPColl)
+
+ val windowedResults = results.apply(
+ "WindowedEvent",
+ ParDo.of(object : DoFn<KV<String, Long>, WindowedEvent>() {
+ @ProcessElement
+ fun processElement(
+ @Element element: KV<String, Long>,
+ window: BoundedWindow, out: OutputReceiver<WindowedEvent>
+ ) {
+
+ out.output(WindowedEvent(element.key, element.value, window.toString()))
+ }
+ })
+ )
+
+ PAssert.that(windowedResults).containsInAnyOrder(
+ WindowedEvent("event", 4L, "[2019-06-01T00:00:00.000Z..2019-06-02T00:00:00.000Z)"),
+ WindowedEvent("event", 2L, "[2019-06-05T00:00:00.000Z..2019-06-06T00:00:00.000Z)"),
+ WindowedEvent("event", 3L, "[2019-06-08T00:00:00.000Z..2019-06-09T00:00:00.000Z)"),
+ WindowedEvent("event", 1L, "[2019-06-10T00:00:00.000Z..2019-06-11T00:00:00.000Z)")
+ )
+
+ testPipeline.run().waitUntilFinish()
+ }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt
new file mode 100644
index 0000000..cf3a300
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.fixedwindow
+
+import java.io.Serializable
+
+data class WindowedEvent(private val event: String?, private val count: Long, private val window: String) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-info.yaml
new file mode 100644
index 0000000..9f65c8a
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Fixed Time Window
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-remote-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-remote-info.yaml
new file mode 100644
index 0000000..ec71e4a
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358538
+update_date: Wed, 20 May 2020 20:29:06 UTC
+unit: 342739
diff --git a/learning/katas/kotlin/Windowing/section-info.yaml b/learning/katas/kotlin/Windowing/section-info.yaml
new file mode 100644
index 0000000..e5121f4
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/section-info.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Adding Timestamp
+- Fixed Time Window
diff --git a/learning/katas/kotlin/Windowing/section-remote-info.yaml b/learning/katas/kotlin/Windowing/section-remote-info.yaml
new file mode 100644
index 0000000..c0ae8e3
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133891
+update_date: Wed, 20 May 2020 20:28:59 UTC
diff --git a/learning/katas/kotlin/build.gradle b/learning/katas/kotlin/build.gradle
new file mode 100644
index 0000000..cb49f0d
--- /dev/null
+++ b/learning/katas/kotlin/build.gradle
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+ ext {
+ beamVersion = '2.19.0'
+ guavaVersion = '28.1-jre'
+ jodaTimeVersion = '2.10.4'
+ slf4jVersion = '1.7.28'
+ log4jSlf4jImpl = '2.12.1'
+ kotlinVersion = '1.3.72'
+
+ assertjVersion = '3.13.2'
+ hamcrestVersion = '2.1'
+ junitVersion = '4.12'
+ }
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
+ }
+}
+
+def printOutput(def output) {
+ return tasks.create("printOutput") {
+ for (line in output.toString().readLines()) {
+ println "#educational_plugin" + line
+ }
+ }
+}
+
+subprojects {
+ apply plugin: 'application'
+ apply plugin: 'java'
+ apply plugin: 'kotlin'
+
+ sourceCompatibility = 1.8
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ compile "org.apache.beam:beam-sdks-java-core:$beamVersion"
+ compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
+ runtime "org.apache.beam:beam-runners-direct-java:$beamVersion"
+
+ compile "joda-time:joda-time:$jodaTimeVersion"
+ compile "org.slf4j:slf4j-api:$slf4jVersion"
+ compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4jSlf4jImpl"
+ compile "com.google.guava:guava:$guavaVersion"
+
+ testCompile "junit:junit:$junitVersion"
+ testCompile "org.hamcrest:hamcrest-core:$hamcrestVersion"
+ testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
+ testCompile "org.assertj:assertj-core:$assertjVersion"
+ }
+
+ compileKotlin.destinationDir = compileJava.destinationDir
+
+ compileKotlin {
+ kotlinOptions.jvmTarget = "1.8"
+ }
+ compileTestKotlin {
+ kotlinOptions.jvmTarget = "1.8"
+ }
+
+ sourceSets {
+ main {
+ java.srcDir 'src'
+ resources.srcDir 'resources'
+ }
+ test {
+ java.srcDir 'test'
+ }
+ }
+
+ mainClassName = project.hasProperty("mainClass") ? project.getProperty("mainClass") : ""
+
+ test {
+ outputs.upToDateWhen { false }
+ afterTest { TestDescriptor test, TestResult result ->
+ if (result.resultType == TestResult.ResultType.FAILURE) {
+ def message = result.exception?.message ?: "Wrong answer"
+ def lines = message.readLines()
+ println "#educational_plugin FAILED + " + lines[0]
+ lines[1..-1].forEach { line ->
+ println "#educational_plugin" + line
+ }
+ // we need this to separate output of different tests
+ println
+ }
+ }
+ }
+
+ def runOutput = new ByteArrayOutputStream()
+ tasks.run.setStandardOutput(runOutput)
+ tasks.run.doLast { printOutput(runOutput) }
+}
+
+project(':util') {
+ dependencies {
+ compile "junit:junit:$junitVersion"
+ }
+}
+
+configure(subprojects.findAll { it.name != 'util' }) {
+ dependencies {
+ compile project(':util').sourceSets.main.output
+ testCompile project(':util').sourceSets.test.output
+ }
+}
+
+wrapper {
+ gradleVersion = '5.0'
+}
diff --git a/learning/katas/kotlin/course-info.yaml b/learning/katas/kotlin/course-info.yaml
new file mode 100644
index 0000000..f090fc9
--- /dev/null
+++ b/learning/katas/kotlin/course-info.yaml
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+title: Beam Katas - Kotlin
+language: English
+summary: "This course provides a series of katas to get familiar with Apache Beam using Kotlin"
+programming_language: Kotlin
+programming_language_version: 1.3
+content:
+- Introduction
+- Core Transforms
+- Common Transforms
+- IO
+- Windowing
+- Triggers
+- Examples
diff --git a/learning/katas/kotlin/course-remote-info.yaml b/learning/katas/kotlin/course-remote-info.yaml
new file mode 100644
index 0000000..fe6bd8d
--- /dev/null
+++ b/learning/katas/kotlin/course-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 72488
+update_date: Sat, 30 May 2020 18:51:41 UTC
diff --git a/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.jar b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..87b738c
Binary files /dev/null and b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.properties b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f71c9f7
--- /dev/null
+++ b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/learning/katas/kotlin/gradlew b/learning/katas/kotlin/gradlew
new file mode 100755
index 0000000..9e22af6
--- /dev/null
+++ b/learning/katas/kotlin/gradlew
@@ -0,0 +1,190 @@
+#!/usr/bin/env sh
+
+################################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+################################################################################
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/learning/katas/kotlin/gradlew.bat b/learning/katas/kotlin/gradlew.bat
new file mode 100644
index 0000000..582415f
--- /dev/null
+++ b/learning/katas/kotlin/gradlew.bat
@@ -0,0 +1,102 @@
+@rem ################################################################################
+@rem # Licensed to the Apache Software Foundation (ASF) under one
+@rem # or more contributor license agreements. See the NOTICE file
+@rem # distributed with this work for additional information
+@rem # regarding copyright ownership. The ASF licenses this file
+@rem # to you under the Apache License, Version 2.0 (the
+@rem # "License"); you may not use this file except in compliance
+@rem # with the License. You may obtain a copy of the License at
+@rem #
+@rem # http://www.apache.org/licenses/LICENSE-2.0
+@rem #
+@rem # Unless required by applicable law or agreed to in writing, software
+@rem # distributed under the License is distributed on an "AS IS" BASIS,
+@rem # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem # See the License for the specific language governing permissions and
+@rem # limitations under the License.
+@rem ################################################################################
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
... 304 lines suppressed ...