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)
|
||||
.build();
|
||||
|
||||
// TODO: make this call async as well.
|
||||
Response response = this.httpClient.newCall(request).execute();
|
||||
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