Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add orThrow and orDefault methods to Index #741

Merged
merged 5 commits into from Apr 2, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
65 changes: 65 additions & 0 deletions api/src/main/java/net/kyori/adventure/util/Index.java
Expand Up @@ -29,9 +29,12 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.Function;
import java.util.function.IntFunction;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -154,6 +157,37 @@ private Index(final Map<K, V> keyToValue, final Map<V, K> valueToKey) {
return this.valueToKey.get(value);
}

/**
* Gets the key for a value or throws an exception.
*
* @param value the value
* @return the key
* @throws NoSuchElementException if there is no key for the value
* @since 4.11.0
*/
public @NotNull K keyOrThrow(final @NotNull V value) {
final K key = this.key(value);
if (key == null) {
throw new NoSuchElementException("There is no key for value " + value);
}
return key;
}

/**
* Gets a key by its value or returns
* a fallback key.
Machine-Maker marked this conversation as resolved.
Show resolved Hide resolved
*
* @param value the value
* @param defaultKey the fallback key
* @return the key
* @since 4.11.0
*/
@Contract("_, null -> null; _, !null -> !null")
public K keyOrDefault(final @NotNull V value, @Nullable K defaultKey) {
Machine-Maker marked this conversation as resolved.
Show resolved Hide resolved
final K key = this.key(value);
return key == null ? defaultKey : key;
}

/**
* Gets the keys.
*
Expand All @@ -175,6 +209,37 @@ private Index(final Map<K, V> keyToValue, final Map<V, K> valueToKey) {
return this.keyToValue.get(key);
}

/**
* Gets a value by its key.
*
* @param key the key
* @return the value
* @throws NoSuchElementException if there is no value for the key
* @since 4.11.0
*/
public @NotNull V valueOrThrow(final @NotNull K key) {
final V value = this.value(key);
if (value == null) {
throw new NoSuchElementException("There is no value for key " + key);
}
return value;
}

/**
* Gets a value by its key or returns
* a fallback value.
Machine-Maker marked this conversation as resolved.
Show resolved Hide resolved
*
* @param key the key
* @param defaultValue the fallback value
* @return the value
* @since 4.11.0
*/
@Contract("_, null -> null; _, !null -> !null")
public V valueOrDefault(final @NotNull K key, @Nullable V defaultValue) {
Machine-Maker marked this conversation as resolved.
Show resolved Hide resolved
final V value = this.value(key);
return value == null ? defaultValue : value;
}

/**
* Get an unmodifiable mapping of index entries from key to value.
*
Expand Down
28 changes: 26 additions & 2 deletions api/src/test/java/net/kyori/adventure/util/IndexTest.java
Expand Up @@ -23,6 +23,7 @@
*/
package net.kyori.adventure.util;

import java.util.NoSuchElementException;
import java.util.UUID;
import org.junit.jupiter.api.Test;

Expand All @@ -31,7 +32,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;

class IndexTest {
private static final Index<String, Thing> THINGS = Index.create(Thing.class, thing -> thing.name);
private static final Index<String, Thing> THINGS = Index.create(Thing.class, thing -> thing.name, Thing.ABC, Thing.DEF);

@Test
void testCreateWithNonUniqueKey() {
Expand All @@ -46,17 +47,39 @@ void testCreateWithNonUniqueValue() {
@Test
void testKey() {
for (final Thing thing : Thing.values()) {
if (thing == Thing.NOT_PRESENT) continue;
assertEquals(thing.name, THINGS.key(thing));
}
}

@Test
void testValue() {
for (final Thing thing : Thing.values()) {
if (thing == Thing.NOT_PRESENT) continue;
assertEquals(thing, THINGS.value(thing.name));
}
}

@Test
void testValueOrThrow() {
assertThrows(NoSuchElementException.class, () -> THINGS.valueOrThrow("__NO_VALUE__"));
}

@Test
void testKeyOrThrow() {
assertThrows(NoSuchElementException.class, () -> THINGS.keyOrThrow(Thing.NOT_PRESENT));
}

@Test
void testValueOrDefault() {
assertEquals(Thing.NOT_PRESENT, THINGS.valueOrDefault("__NO_VALUE__", Thing.NOT_PRESENT));
}

@Test
void testKeyOrDefault() {
assertEquals("__DEFAULT__", THINGS.keyOrDefault(Thing.NOT_PRESENT, "__DEFAULT__"));
}

@Test
void testKeys() {
assertThat(THINGS.keys()).containsExactly("abc", "def");
Expand All @@ -69,7 +92,8 @@ void testValues() {

private enum Thing {
ABC("abc"),
DEF("def");
DEF("def"),
NOT_PRESENT("not_present");

private final String name;

Expand Down