mirror of https://github.com/dapr/java-sdk.git
ActorTypeInformation with parsing logic + some stubs.
This commit is contained in:
parent
937224e2f3
commit
9dd68c8f71
|
|
@ -171,6 +171,7 @@ class DaprHttpAsyncClient implements DaprAsyncClient {
|
||||||
.addHeader(Constants.HEADER_DAPR_REQUEST_ID, requestId)
|
.addHeader(Constants.HEADER_DAPR_REQUEST_ID, requestId)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
// TODO: make this call async as well.
|
||||||
Response response = this.httpClient.newCall(request).execute();
|
Response response = this.httpClient.newCall(request).execute();
|
||||||
if (!response.isSuccessful())
|
if (!response.isSuccessful())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
* Licensed under the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.dapr.actors.runtime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public abstract class AbstractActor {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
* Licensed under the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.dapr.actors.runtime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public interface Actor {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
* Licensed under the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.dapr.actors.runtime;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation to override default behavior of Actor class.
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface ActorType {
|
||||||
|
|
||||||
|
String Name();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2019 Swen Schisler <swen.schisler@fourtytwosoft.io>.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package io.dapr.actors.runtime;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the information about the class implementing an actor.
|
||||||
|
*
|
||||||
|
* @author Swen Schisler <swen.schisler@fourtytwosoft.io>
|
||||||
|
* @author Artur Souza <artur.barbalho@microsoft.com>
|
||||||
|
*/
|
||||||
|
public final class ActorTypeInformation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor type's name.
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor's implementation class.
|
||||||
|
*/
|
||||||
|
private final Class implementationClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor's immediate interfaces.
|
||||||
|
*/
|
||||||
|
private final Collection<Class> interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether Actor type is abstract.
|
||||||
|
*/
|
||||||
|
private final boolean abstractClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether Actor type is remindable.
|
||||||
|
*/
|
||||||
|
private final boolean remindable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new {@link ActorTypeInformation}
|
||||||
|
* @param name Actor type's name.
|
||||||
|
* @param implementationClass Actor's implementation class.
|
||||||
|
* @param interfaces Actor's immediate interfaces.
|
||||||
|
* @param abstractClass Whether Actor type is abstract.
|
||||||
|
* @param remindable Whether Actor type is remindable.
|
||||||
|
*/
|
||||||
|
private ActorTypeInformation(String name,
|
||||||
|
Class implementationClass,
|
||||||
|
Collection<Class> interfaces,
|
||||||
|
boolean abstractClass,
|
||||||
|
boolean remindable) {
|
||||||
|
this.name = name;
|
||||||
|
this.implementationClass = implementationClass;
|
||||||
|
this.interfaces = interfaces;
|
||||||
|
this.abstractClass = abstractClass;
|
||||||
|
this.remindable = remindable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of this ActorType.
|
||||||
|
* @return ActorType's name.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of the class implementing the actor.
|
||||||
|
*
|
||||||
|
* @return The {@link Class} of implementing the actor.
|
||||||
|
*/
|
||||||
|
public Class getImplementationClass() {
|
||||||
|
return this.implementationClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the actor interfaces which derive from {@link Actor} and implemented by actor class.
|
||||||
|
*
|
||||||
|
* @return Collection of actor interfaces.
|
||||||
|
*/
|
||||||
|
public Collection<Class> getInterfaces() {
|
||||||
|
return Collections.unmodifiableCollection(this.interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a value indicating whether the class implementing actor is abstract.
|
||||||
|
*
|
||||||
|
* @return true if the class implementing actor is abstract, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean isAbstractClass() {
|
||||||
|
return this.abstractClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a value indicating whether the actor class implements {@link Remindable}.
|
||||||
|
*
|
||||||
|
* @return true if the actor class implements {@link Remindable}.
|
||||||
|
*/
|
||||||
|
public boolean isRemindable() {
|
||||||
|
return this.remindable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the {@link ActorTypeInformation} from given Class.
|
||||||
|
*
|
||||||
|
* @param actorClass The type of class implementing the actor to create ActorTypeInformation for.
|
||||||
|
* @return ActorTypeInformation if successfully created for actorType or null.
|
||||||
|
*/
|
||||||
|
public static ActorTypeInformation tryCreate(Class actorClass) {
|
||||||
|
try {
|
||||||
|
return create(actorClass);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link #ActorTypeInformation} from actorType.
|
||||||
|
*
|
||||||
|
* @param actorClass The class implementing the actor to create ActorTypeInformation for.
|
||||||
|
* @return {@link #ActorTypeInformation} created from actorType.
|
||||||
|
*/
|
||||||
|
public static ActorTypeInformation create(Class actorClass) {
|
||||||
|
if (!ActorTypeUtilities.isActor(actorClass)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"The type '%s' is not an Actor. An actor type must derive from '%s'.",
|
||||||
|
actorClass == null ? "" : actorClass.getCanonicalName(),
|
||||||
|
Actor.class.getCanonicalName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all actor interfaces
|
||||||
|
Class<?>[] actorInterfaces = actorClass.getInterfaces();
|
||||||
|
|
||||||
|
boolean isAbstract = Modifier.isAbstract(actorClass.getModifiers());
|
||||||
|
// ensure that the if the actor type is not abstract it implements at least one actor interface
|
||||||
|
if ((actorInterfaces.length == 0) && !isAbstract) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"The actor type '%s' does not implement any actor interfaces or one of the " +
|
||||||
|
"interfaces implemented is not an actor interface. " +
|
||||||
|
"All interfaces(including its parent interface) implemented by actor type must " +
|
||||||
|
"be actor interface. An actor interface is the one that ultimately derives " +
|
||||||
|
"from '%s' type.",
|
||||||
|
actorClass == null ? "" : actorClass.getCanonicalName(),
|
||||||
|
Actor.class.getCanonicalName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isRemindable = ActorTypeUtilities.isRemindableActor(actorClass);
|
||||||
|
ActorType actorTypeAnnotation = (ActorType) actorClass.getAnnotation(ActorType.class);
|
||||||
|
String typeName = actorTypeAnnotation != null ? actorTypeAnnotation.Name() : actorClass.getSimpleName();
|
||||||
|
|
||||||
|
return new ActorTypeInformation(typeName, actorClass, Arrays.asList(actorInterfaces), isAbstract, isRemindable);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
* Licensed under the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.dapr.actors.runtime;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to extract information on Actor type.
|
||||||
|
*/
|
||||||
|
final class ActorTypeUtilities {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all interfaces that extend Actor.
|
||||||
|
* @param clazz Actor class.
|
||||||
|
* @return Array of Actor interfaces.
|
||||||
|
*/
|
||||||
|
public static Class[] getActorInterfaces(Class clazz) {
|
||||||
|
if (clazz == null) {
|
||||||
|
return new Class[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return Arrays.stream(clazz.getInterfaces())
|
||||||
|
.filter(t -> Actor.class.isAssignableFrom(t))
|
||||||
|
.filter(t -> getNonActorParentClass(t) == null)
|
||||||
|
.toArray(Class[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if given class is an Actor interface.
|
||||||
|
* @param clazz Actor interface candidate.
|
||||||
|
* @return Whether this is an Actor interface.
|
||||||
|
*/
|
||||||
|
public static boolean isActorInterface(Class clazz) {
|
||||||
|
return (clazz != null) && clazz.isInterface() && (getNonActorParentClass(clazz) == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether this is an Actor class.
|
||||||
|
* @param clazz Actor class candidate.
|
||||||
|
* @return Whether this is an Actor class.
|
||||||
|
*/
|
||||||
|
public static boolean isActor(Class clazz) {
|
||||||
|
if (clazz == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AbstractActor.class.isAssignableFrom(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether this is an remindable Actor.
|
||||||
|
* @param clazz Actor class.
|
||||||
|
* @return Whether this is an remindable Actor.
|
||||||
|
*/
|
||||||
|
public static boolean isRemindableActor(Class clazz) {
|
||||||
|
return (clazz != null) && isActor(clazz) && (Arrays.stream(clazz.getInterfaces()).filter(t -> t.equals(Remindable.class)).count() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parent class if it is not the {@link AbstractActor} parent class.
|
||||||
|
* @param clazz Actor class.
|
||||||
|
* @return Parent class or null if it is {@link AbstractActor}.
|
||||||
|
*/
|
||||||
|
public static Class getNonActorParentClass(Class clazz) {
|
||||||
|
if (clazz == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class[] items = Arrays.stream(clazz.getInterfaces()).filter(t -> !t.equals(Actor.class)).toArray(Class[]::new);
|
||||||
|
if (items.length == 0) {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Class c : items) {
|
||||||
|
Class nonActorParent = getNonActorParentClass(c);
|
||||||
|
if (nonActorParent != null) {
|
||||||
|
return nonActorParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
* Licensed under the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.dapr.actors.runtime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public interface Remindable {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
* Licensed under the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.dapr.actors.runtime;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for ActorTypeInformation.
|
||||||
|
*/
|
||||||
|
public class ActorTypeInformationTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor interfaced used in this test only.
|
||||||
|
*/
|
||||||
|
private interface MyActor extends Actor {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks information for a non-remindable actor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void notRemindable() {
|
||||||
|
|
||||||
|
class A extends AbstractActor implements MyActor {
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorTypeInformation info = ActorTypeInformation.create(A.class);
|
||||||
|
Assert.assertNotNull(info);
|
||||||
|
Assert.assertEquals("A", info.getName());
|
||||||
|
Assert.assertEquals(A.class, info.getImplementationClass());
|
||||||
|
Assert.assertFalse(info.isAbstractClass());
|
||||||
|
Assert.assertFalse(info.isRemindable());
|
||||||
|
Assert.assertEquals(1, info.getInterfaces().size());
|
||||||
|
Assert.assertTrue(info.getInterfaces().contains(MyActor.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks information for a remindable actor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void remindable() {
|
||||||
|
|
||||||
|
class A extends AbstractActor implements MyActor, Remindable {
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorTypeInformation info = ActorTypeInformation.create(A.class);
|
||||||
|
Assert.assertNotNull(info);
|
||||||
|
Assert.assertEquals("A", info.getName());
|
||||||
|
Assert.assertEquals(A.class, info.getImplementationClass());
|
||||||
|
Assert.assertFalse(info.isAbstractClass());
|
||||||
|
Assert.assertTrue(info.isRemindable());
|
||||||
|
Assert.assertEquals(2, info.getInterfaces().size());
|
||||||
|
Assert.assertTrue(info.getInterfaces().contains(Remindable.class));
|
||||||
|
Assert.assertTrue(info.getInterfaces().contains(MyActor.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks information for an actor renamed via annotation.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void renamedWithAnnotation() {
|
||||||
|
@ActorType(Name = "B")
|
||||||
|
class A extends AbstractActor implements MyActor {
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorTypeInformation info = ActorTypeInformation.create(A.class);
|
||||||
|
Assert.assertNotNull(info);
|
||||||
|
Assert.assertEquals("B", info.getName());
|
||||||
|
Assert.assertEquals(A.class, info.getImplementationClass());
|
||||||
|
Assert.assertFalse(info.isAbstractClass());
|
||||||
|
Assert.assertFalse(info.isRemindable());
|
||||||
|
Assert.assertEquals(1, info.getInterfaces().size());
|
||||||
|
Assert.assertTrue(info.getInterfaces().contains(MyActor.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks information for an actor is invalid due to an non-actor parent.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void nonActorParentClass() {
|
||||||
|
abstract class MyAbstractClass extends AbstractActor implements MyActor {
|
||||||
|
}
|
||||||
|
|
||||||
|
class A extends MyAbstractClass {
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorTypeInformation info = ActorTypeInformation.tryCreate(A.class);
|
||||||
|
Assert.assertNull(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue