-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor/container adapter register (#151)
* feat(ContainerAdapterRegister): add an adapter and adapter manager for converting an object into a container (GitHub #149) * refactor(DynamicContainerOperatorProxyMethodFactory): replace local container adapters with global container adapters (GitHub #149)
1 parent
f9a24cf
commit 17ce3a5
Showing
7 changed files
with
276 additions
and
83 deletions.
There are no files selected for viewing
71 changes: 71 additions & 0 deletions
71
crane4j-core/src/main/java/cn/crane4j/core/support/ContainerAdapterRegister.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package cn.crane4j.core.support; | ||
|
||
import cn.crane4j.core.container.Container; | ||
import org.checkerframework.checker.nullness.qual.NonNull; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
import java.util.Optional; | ||
|
||
/** | ||
* Container adapter register. | ||
* | ||
* @author huangchengxing | ||
* @see DefaultContainerAdapterRegister | ||
* @since 2.2.0 | ||
*/ | ||
public interface ContainerAdapterRegister { | ||
|
||
/** | ||
* Get target type. | ||
* | ||
* @param targetType target type | ||
* @return {@link Adapter} instance. | ||
*/ | ||
@Nullable | ||
Adapter getAdapter(Class<?> targetType); | ||
|
||
/** | ||
* Register adapter. | ||
* | ||
* @param targetType target type | ||
* @param adapter adapter | ||
*/ | ||
void registerAdapter(Class<?> targetType, Adapter adapter); | ||
|
||
/** | ||
* Wrap target to {@link Container} if possible. | ||
* | ||
* @param namespace namespace of container | ||
* @param target target | ||
* @param <T> key type of container | ||
* @return {@link Container} instant if possible, null otherwise | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
@Nullable | ||
default <T> Container<T> wrapIfPossible(String namespace, Object target) { | ||
return (Container<T>)Optional.ofNullable(target) | ||
.map(Object::getClass) | ||
.map(this::getAdapter) | ||
.map(adapter -> adapter.wrapIfPossible(namespace, target)) | ||
.orElse(null); | ||
} | ||
|
||
/** | ||
* An adapter for wrap object to {@link Container}. | ||
* | ||
* @author huangchengxing | ||
*/ | ||
@FunctionalInterface | ||
interface Adapter { | ||
|
||
/** | ||
* Wrap target to {@link Container} if possible. | ||
* | ||
* @param namespace namespace of container | ||
* @param target target | ||
* @return {@link Container} instant if possible, null otherwise | ||
*/ | ||
@Nullable | ||
Container<Object> wrapIfPossible(String namespace, @NonNull Object target); | ||
} | ||
} |
81 changes: 81 additions & 0 deletions
81
crane4j-core/src/main/java/cn/crane4j/core/support/DefaultContainerAdapterRegister.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package cn.crane4j.core.support; | ||
|
||
import cn.crane4j.core.container.Container; | ||
import cn.crane4j.core.container.Containers; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Default implementation for {@link DefaultContainerAdapterRegister}. | ||
* | ||
* @author huangchengxing | ||
* @since 2.2.0 | ||
*/ | ||
public class DefaultContainerAdapterRegister implements ContainerAdapterRegister { | ||
|
||
/** | ||
* default global instance. | ||
*/ | ||
public static final DefaultContainerAdapterRegister INSTANCE = new DefaultContainerAdapterRegister(); | ||
|
||
/** | ||
* registered adapters | ||
*/ | ||
protected final Map<Class<?>, Adapter> registeredAdapters = new LinkedHashMap<>(); | ||
|
||
/** | ||
* Create instance with default adapters. | ||
*/ | ||
public DefaultContainerAdapterRegister() { | ||
initDefaultAdapters(); | ||
} | ||
|
||
/** | ||
* Init default adapters. | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
protected void initDefaultAdapters() { | ||
registerAdapter(Map.class, (n, t) -> Containers.forMap(n, (Map<Object, ?>) t)); | ||
registerAdapter(Container.class, (n, t) -> (Container<Object>)t); | ||
registerAdapter(DataProvider.class, (n, t) -> Containers.forLambda(n, (DataProvider<Object, Object>) t)); | ||
} | ||
|
||
/** | ||
* Get target type. | ||
* | ||
* @param targetType target type | ||
* @return {@link Adapter} instance. | ||
*/ | ||
@Nullable | ||
@Override | ||
public Adapter getAdapter(Class<?> targetType) { | ||
return findAdaptor(targetType); | ||
} | ||
|
||
/** | ||
* Register adapter. | ||
* | ||
* @param targetType target type | ||
* @param adapter adapter | ||
*/ | ||
@Override | ||
public void registerAdapter(Class<?> targetType, Adapter adapter) { | ||
registeredAdapters.put(targetType, adapter); | ||
} | ||
|
||
@Nullable | ||
private Adapter findAdaptor(Class<?> targetType) { | ||
Adapter adapter = registeredAdapters.get(targetType); | ||
if (Objects.nonNull(adapter)) { | ||
return adapter; | ||
} | ||
return registeredAdapters.entrySet().stream() | ||
.filter(e -> e.getKey().isAssignableFrom(targetType)) | ||
.findFirst() | ||
.map(Map.Entry::getValue) | ||
.orElse(null); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
crane4j-core/src/test/java/cn/crane4j/core/support/DefaultContainerAdapterRegisterTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package cn.crane4j.core.support; | ||
|
||
import cn.crane4j.core.container.Container; | ||
import cn.crane4j.core.container.Containers; | ||
import cn.crane4j.core.container.LambdaContainer; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* test for {@link DefaultContainerAdapterRegister} | ||
* | ||
* @author huangchengxing | ||
*/ | ||
public class DefaultContainerAdapterRegisterTest { | ||
|
||
private DefaultContainerAdapterRegister register = new DefaultContainerAdapterRegister(); | ||
|
||
@Test | ||
public void testRegisterAdapter() { | ||
DefaultContainerAdapterRegister register = new DefaultContainerAdapterRegister(); | ||
Assert.assertNull(register.getAdapter(Void.TYPE)); | ||
ContainerAdapterRegister.Adapter adapter = (ns, t) -> Containers.empty(); | ||
register.registerAdapter(Void.TYPE, adapter); | ||
Assert.assertSame(adapter, register.getAdapter(Void.TYPE)); | ||
} | ||
|
||
@Test | ||
public void testAdaptFunction() { | ||
ContainerAdapterRegister.Adapter functionAdapter = register.getAdapter(DataProvider.class); | ||
Assert.assertNotNull(functionAdapter); | ||
DataProvider<Object, Object> dp = ids -> Collections.emptyMap(); | ||
Assert.assertEquals(functionAdapter, register.getAdapter(dp.getClass())); | ||
Container<Object> functionContainer = register.wrapIfPossible("test", dp); | ||
Assert.assertNotNull(functionContainer); | ||
Assert.assertEquals("test", functionContainer.getNamespace()); | ||
} | ||
@Test | ||
public void testAdaptContainer() { | ||
ContainerAdapterRegister.Adapter containerAdapter = register.getAdapter(LambdaContainer.class); | ||
Assert.assertNotNull(containerAdapter); | ||
Assert.assertEquals(containerAdapter, register.getAdapter(Container.class)); | ||
Container<Object> container = Containers.empty(); | ||
Assert.assertSame(container, register.wrapIfPossible(Container.EMPTY_CONTAINER_NAMESPACE, container)); | ||
} | ||
|
||
@Test | ||
public void testAdaptMap() { | ||
ContainerAdapterRegister.Adapter mapAdapter = register.getAdapter(LinkedHashMap.class); | ||
Assert.assertNotNull(mapAdapter); | ||
Assert.assertSame(mapAdapter, register.getAdapter(Map.class)); | ||
Map<String, Object> map = new HashMap<>(); | ||
Assert.assertEquals(map, register.wrapIfPossible("test", map).get(Collections.emptyList())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters