Skip to content

Commit

Permalink
✨ TypedRef to ref k-v type #50
Browse files Browse the repository at this point in the history
  • Loading branch information
trydofor committed Jan 23, 2025
1 parent 14979bf commit 9603e66
Show file tree
Hide file tree
Showing 8 changed files with 670 additions and 31 deletions.
3 changes: 0 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,8 @@
<configuration>
<excludes>
<!-- mark or assert -->
<exclude>**/best/Dummy*</exclude>
<exclude>**/best/Param*</exclude>
<exclude>**/best/Typed*</exclude>
<!-- data struct -->
<exclude>**/data/DataResult.*</exclude>
<exclude>**/data/Null*</exclude>
<exclude>**/data/Q.*</exclude>
<exclude>**/data/Q$*</exclude>
Expand Down
54 changes: 44 additions & 10 deletions src/main/java/pro/fessional/mirana/best/TypedKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

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

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
* <pre>
Expand Down Expand Up @@ -43,22 +44,55 @@ protected TypedKey() {
INSTANCE.put(clz.getName(), this);
}

@SuppressWarnings("unchecked")
@Nullable
public V get(@NotNull Map<?, ?> map) throws ClassCastException {
final Object o = map.get(this);
return (V) o;
public void set(@NotNull BiConsumer<TypedKey<V>, V> fun, V value) {
fun.accept(this, value);
}

public void set(@NotNull Map<TypedKey<V>, ? super V> map, V value) {
map.put(this, value);
}

@Contract("_,true->!null")
public V get(@NotNull Function<TypedKey<V>, V> fun, boolean nonnull) {
V obj = fun.apply(this);
if (obj == null && nonnull) {
throw new NullPointerException("cannot be null, regType=" + regType);
}
return obj;
}

@Contract("_,true->!null")
public V get(@NotNull Map<TypedKey<V>, ? extends V> map, boolean nonnull) {
V obj = map.get(this);
if (obj == null && nonnull) {
throw new NullPointerException("cannot be null, regType=" + regType);
}
return obj;
}

@Contract("_,!null ->!null")
public V getOr(@NotNull Function<TypedKey<V>, V> fun, V elze) {
final V obj = fun.apply(this);
return obj != null ? obj : elze;
}

@Contract("_,!null ->!null")
public V getOr(@NotNull Map<?, ?> map, V elze) throws ClassCastException {
final V obj = get(map);
public V getOr(@NotNull Map<TypedKey<V>, ? extends V> map, V elze) {
final V obj = map.get(this);
return obj != null ? obj : elze;
}

@SuppressWarnings("unchecked")
@Contract("_,!null ->!null")
public V tryOr(@Nullable Object obj, V elze) throws ClassCastException {
public V tryOr(@NotNull Function<TypedKey<V>, ?> fun, V elze) throws ClassCastException {
final Object obj = fun.apply(this);
return obj != null ? (V) obj : elze;
}

@SuppressWarnings("unchecked")
@Contract("_,!null ->!null")
public V tryOr(@NotNull Map<?, ?> map, V elze) throws ClassCastException {
final Object obj = map.get(this);
return obj != null ? (V) obj : elze;
}

Expand Down Expand Up @@ -108,7 +142,7 @@ public static <K> TypedKey<K> deserialize(@NotNull String clz) {
public static <K> TypedKey<K> deserialize(@NotNull String clz, boolean nonnull) {
TypedKey<?> ins = INSTANCE.get(clz);
if (ins == null && nonnull) {
throw new ClassCastException("instance not found, class=" + clz);
throw new NullPointerException("instance not found, class=" + clz);
}
else {
return (TypedKey<K>) ins;
Expand Down
103 changes: 103 additions & 0 deletions src/main/java/pro/fessional/mirana/best/TypedRef.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package pro.fessional.mirana.best;


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

import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
* <pre>
* Usage: mark value and its ref type.
* {@code
* Map<String, Integer> map = new HashMap<>();
* TypedRef<String, Integer> ref = new TypedRef<>("key");
* map.put("key", 42);
* Integer result = ref.get(map, false);
* }
* </pre>
*
* @author trydofor
* @since 2025-01-21
*/
public class TypedRef<V, R> {
@NotNull
public final V value;

public TypedRef(@NotNull V value) {
this.value = value;
}

public void set(@NotNull BiConsumer<V, R> fun, R refer) {
fun.accept(value, refer);
}

public void set(@NotNull Map<V, ? super R> map, R refer) {
map.put(value, refer);
}

@Contract("_,true->!null")
public R get(@NotNull Function<V, R> fun, boolean nonnull) {
R obj = fun.apply(value);
if (obj == null && nonnull) {
throw new NullPointerException("cannot be null, value=" + value);
}
return obj;
}

@Contract("_,true->!null")
public R get(@NotNull Map<V, ? extends R> map, boolean nonnull) {
R obj = map.get(value);
if (obj == null && nonnull) {
throw new NullPointerException("cannot be null, value=" + value);
}
return obj;
}

@Contract("_,!null ->!null")
public R getOr(@NotNull Function<V, R> fun, R elze) {
final R obj = fun.apply(value);
return obj != null ? obj : elze;
}

@Contract("_,!null ->!null")
public R getOr(@NotNull Map<V, ? extends R> map, R elze) {
final R obj = map.get(value);
return obj != null ? obj : elze;
}

@SuppressWarnings("unchecked")
@Contract("_,!null ->!null")
public R tryOr(@NotNull Function<V, ?> fun, R elze) throws ClassCastException {
final Object obj = fun.apply(value);
return obj != null ? (R) obj : elze;
}

@SuppressWarnings("unchecked")
@Contract("_,!null ->!null")
public R tryOr(@NotNull Map<?, ?> map, R elze) throws ClassCastException {
final Object obj = map.get(value);
return obj != null ? (R) obj : elze;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TypedRef<?, ?> typedRef = (TypedRef<?, ?>) o;
return Objects.equals(value, typedRef.value);
}

@Override
public int hashCode() {
return Objects.hashCode(value);
}

@Override
public String toString() {
return value.toString();
}
}
59 changes: 47 additions & 12 deletions src/main/java/pro/fessional/mirana/best/TypedReg.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
* <pre>
Expand Down Expand Up @@ -47,6 +49,10 @@ protected TypedReg() {
INSTANCE.put(clz.getName(), this);
}

public Key<K, V> key(K key) {
return new Key<>(this, key);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down Expand Up @@ -93,17 +99,13 @@ public static <K, V> TypedReg<K, V> deserialize(@NotNull String clz) {
public static <K, V> TypedReg<K, V> deserialize(@NotNull String clz, boolean nonnull) {
TypedReg<?, ?> ins = INSTANCE.get(clz);
if (ins == null && nonnull) {
throw new ClassCastException("instance not found, class=" + clz);
throw new NullPointerException("instance not found, class=" + clz);
}
else {
return (TypedReg<K, V>) ins;
}
}

public static <K, V> Key<K, V> key(@NotNull TypedReg<K, V> reg, K key) {
return new Key<>(reg, key);
}

public static class Key<K, V> {
@NotNull
public final TypedReg<K, V> reg;
Expand All @@ -114,22 +116,55 @@ public Key(@NotNull TypedReg<K, V> reg, K key) {
this.key = key;
}

@SuppressWarnings("unchecked")
public void set(@NotNull BiConsumer<Key<K, V>, V> fun, V value) {
fun.accept(this, value);
}

public void set(@NotNull Map<Key<K, V>, ? super V> map, V value) {
map.put(this, value);
}

@Nullable
public V get(@NotNull Map<?, ?> map) throws ClassCastException {
final Object o = map.get(this);
return (V) o;
public V get(@NotNull Function<Key<K, V>, V> fun, boolean nonnull) {
V obj = fun.apply(this);
if (obj == null && nonnull) {
throw new NullPointerException("cannot be null, key=" + key + ", reg=" + reg);
}
return obj;
}

@Nullable
public V get(@NotNull Map<Key<K, V>, ? extends V> map, boolean nonnull) {
V obj = map.get(this);
if (obj == null && nonnull) {
throw new NullPointerException("cannot be null, key=" + key + ", reg=" + reg);
}
return obj;
}

@Contract("_,!null ->!null")
public V getOr(@NotNull Function<Key<K, V>, V> fun, V elze) {
final V obj = fun.apply(this);
return obj != null ? obj : elze;
}

@Contract("_,!null ->!null")
public V getOr(@NotNull Map<?, ?> map, V elze) throws ClassCastException {
final V obj = get(map);
public V getOr(@NotNull Map<Key<K, V>, ? extends V> map, V elze) {
final V obj = map.get(this);
return obj != null ? obj : elze;
}

@SuppressWarnings("unchecked")
@Contract("_,!null ->!null")
public V tryOr(@Nullable Object obj, V elze) throws ClassCastException {
public V tryOr(@NotNull Function<Key<K, V>, ?> fun, V elze) throws ClassCastException {
final Object obj = fun.apply(this);
return obj != null ? (V) obj : elze;
}

@SuppressWarnings("unchecked")
@Contract("_,!null ->!null")
public V tryOr(@NotNull Map<?, ?> map, V elze) throws ClassCastException {
final Object obj = map.get(this);
return obj != null ? (V) obj : elze;
}

Expand Down
64 changes: 64 additions & 0 deletions src/test/java/pro/fessional/mirana/best/DummyBlockTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package pro.fessional.mirana.best;

import org.junit.jupiter.api.Test;

import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class DummyBlockTest {

@Test
void testIgnore() {
AtomicReference<Throwable> captured = new AtomicReference<>();
DummyBlock.TweakIgnore.tweakGlobal(captured::set);

Throwable testException = new RuntimeException("Test exception");
DummyBlock.ignore(testException);

assertEquals(testException, captured.get());

DummyBlock.TweakIgnore.resetGlobal();
}

@Test
void testIgnoreWithoutHandler() {
// Test ignore with no handler set
Throwable testException = new RuntimeException("Test exception");
assertDoesNotThrow(() -> DummyBlock.ignore(testException));
}

@Test
void testEmpty() {
assertDoesNotThrow(DummyBlock::empty);
}

@Test
void testNever() {
IllegalStateException exception = assertThrows(IllegalStateException.class, DummyBlock::never);
assertEquals("should NOT invoke NEVER", exception.getMessage());

exception = assertThrows(IllegalStateException.class, () -> DummyBlock.never("Custom message"));
assertEquals("should NOT invoke NEVER:Custom message", exception.getMessage());
}

@Test
void testTodo() {
IllegalStateException exception = assertThrows(IllegalStateException.class, DummyBlock::todo);
assertEquals("should NOT invoke TODO", exception.getMessage());

exception = assertThrows(IllegalStateException.class, () -> DummyBlock.todo("Custom message"));
assertEquals("should NOT invoke TODO:Custom message", exception.getMessage());
}

@Test
void testFixme() {
IllegalStateException exception = assertThrows(IllegalStateException.class, DummyBlock::fixme);
assertEquals("should NOT invoke FIXME", exception.getMessage());

exception = assertThrows(IllegalStateException.class, () -> DummyBlock.fixme("Custom message"));
assertEquals("should NOT invoke FIXME:Custom message", exception.getMessage());
}
}
Loading

0 comments on commit 9603e66

Please sign in to comment.