From 94c3d2a9736a2a29ebb86cd0edfaa9092aae0c32 Mon Sep 17 00:00:00 2001 From: aleksandrsorlovs Date: Mon, 16 Apr 2018 07:48:51 +0300 Subject: [PATCH] Add collection-like extensions to ClipData. --- .../androidx/core/content/ClipDataTest.kt | 143 ++++++++++++++++++ .../java/androidx/core/content/ClipData.kt | 79 ++++++++++ 2 files changed, 222 insertions(+) create mode 100644 src/androidTest/java/androidx/core/content/ClipDataTest.kt create mode 100644 src/main/java/androidx/core/content/ClipData.kt diff --git a/src/androidTest/java/androidx/core/content/ClipDataTest.kt b/src/androidTest/java/androidx/core/content/ClipDataTest.kt new file mode 100644 index 00000000..7c19a65b --- /dev/null +++ b/src/androidTest/java/androidx/core/content/ClipDataTest.kt @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed 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 androidx.core.content + +import android.content.ClipData +import android.content.ClipDescription +import androidx.testutils.assertThrows +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertSame +import org.junit.Assert.assertTrue +import org.junit.Test + +class ClipDataTest { + + private val clip = ClipData("", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN), ClipData.Item("")) + + @Test fun get() { + clip.addItem(ClipData.Item("")) + clip.addItem(ClipData.Item("")) + + for (index in 0 until clip.itemCount) { + assertSame(clip.getItemAt(index), clip[index]) + } + assertThrows { + clip[-1] + } + assertThrows { + clip[clip.itemCount] + } + } + + @Test fun contains() { + val item1 = ClipData.Item("") + assertFalse(item1 in clip) + clip.addItem(item1) + assertTrue(item1 in clip) + + val item2 = ClipData.Item("") + assertFalse(item2 in clip) + clip.addItem(item2) + assertTrue(item2 in clip) + } + + @Test fun plusAssign() { + val items = listOf(ClipData.Item(""), ClipData.Item("")) + val expectedSize = clip.itemCount + items.size + + items.forEach { + clip += it + assertSame(clip.getItemAt(clip.itemCount - 1), it) + } + assertEquals(clip.itemCount, expectedSize) + } + + @Test fun size() { + assertEquals(clip.itemCount, clip.size) + clip.addItem(ClipData.Item("")) + assertEquals(clip.itemCount, clip.size) + clip.addItem(ClipData.Item("")) + assertEquals(clip.itemCount, clip.size) + } + + @Test fun forEach() { + clip.addItem(ClipData.Item("")) + clip.addItem(ClipData.Item("")) + + var iterations = 0 + clip.forEach { + assertSame(clip.getItemAt(iterations), it) + iterations++ + } + assertEquals(clip.itemCount, iterations) + } + + @Test fun forEachIndexed() { + clip.addItem(ClipData.Item("")) + clip.addItem(ClipData.Item("")) + + var iterations = 0 + clip.forEachIndexed { index, item -> + assertEquals(iterations, index) + assertSame(clip.getItemAt(iterations), item) + iterations++ + } + assertEquals(clip.itemCount, iterations) + } + + @Test fun iterator() { + clip.addItem(ClipData.Item("")) + clip.addItem(ClipData.Item("")) + val iterator = clip.iterator() + + for (index in 0 until clip.itemCount) { + assertTrue(iterator.hasNext()) + assertSame(clip.getItemAt(index), iterator.next()) + } + assertFalse(iterator.hasNext()) + assertThrows { + iterator.next() + } + } + + @Test fun iteratorForEach() { + clip.addItem(ClipData.Item("")) + clip.addItem(ClipData.Item("")) + + var iterations = 0 + for (item in clip) { + assertSame(clip.getItemAt(iterations), item) + iterations++ + } + assertEquals(clip.itemCount, iterations) + } + + @Test fun items() { + clip.addItem(ClipData.Item("")) + clip.addItem(ClipData.Item("")) + + var iterations = 0 + clip.items.forEachIndexed { index, item -> + assertEquals(iterations, index) + assertSame(clip.getItemAt(iterations), item) + iterations++ + } + assertEquals(clip.itemCount, iterations) + } + +} \ No newline at end of file diff --git a/src/main/java/androidx/core/content/ClipData.kt b/src/main/java/androidx/core/content/ClipData.kt new file mode 100644 index 00000000..6dadc9f3 --- /dev/null +++ b/src/main/java/androidx/core/content/ClipData.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed 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. + */ + +@file:Suppress("NOTHING_TO_INLINE") + +package androidx.core.content + +import android.content.ClipData + +/** + * Returns the item at [index]. + * + * @throws IndexOutOfBoundsException if index is less than 0 or greater than or equal to the count. + */ +operator fun ClipData.get(index: Int): ClipData.Item { + return if (index < 0 || index >= itemCount) + throw IndexOutOfBoundsException("Index: $index, Size: $itemCount") + else getItemAt(index) +} + +/** Returns `true` if [item] is found in this clip. */ +inline operator fun ClipData.contains(item: ClipData.Item): Boolean { + for (index in 0 until itemCount) { + if (getItemAt(index) == item) { + return true + } + } + return false +} + +/** + * Adds [item] to this clip. + * + * @see ClipData.addItem + */ +inline operator fun ClipData.plusAssign(item: ClipData.Item) = addItem(item) + +/** Returns the number of items in this clip data. */ +inline val ClipData.size get() = itemCount + +/** Performs the given action on each item in this clip data. */ +inline fun ClipData.forEach(action: (item: ClipData.Item) -> Unit) { + for (index in 0 until itemCount) { + action(getItemAt(index)) + } +} + +/** Performs the given action on each item in this clip data, providing its sequential index. */ +inline fun ClipData.forEachIndexed(action: (index: Int, item: ClipData.Item) -> Unit) { + for (index in 0 until itemCount) { + action(index, getItemAt(index)) + } +} + +/** Returns a [Iterator] over the items in this clip. */ +operator fun ClipData.iterator() = object : Iterator { + private var index = 0 + override fun hasNext() = index < itemCount + override fun next() = getItemAt(index++) ?: throw IndexOutOfBoundsException() +} + +/** Returns a [Sequence] over the items in this clip. */ +val ClipData.items: Sequence + get() = object : Sequence { + override fun iterator() = this@items.iterator() + }