com.github.dm.jrt.object.InvocationTarget Maven / Gradle / Ivy
Show all versions of jroutine-object Show documentation
/*
* Copyright 2016 Davide Maestroni
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.dm.jrt.object;
import com.github.dm.jrt.core.util.ConstantConditions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference;
/**
* Class representing an invocation target.
*
* The target identifies a class or an instance whose methods are to be called asynchronously.
*
* No strong reference to the target object will be retained, so, it's up to the caller to ensure
* that it does not get garbage collected.
*
* Created by davide-maestroni on 08/20/2015.
*
* @param the target object type.
*/
public abstract class InvocationTarget {
/**
* Avoid explicit instantiation.
*/
private InvocationTarget() {
}
/**
* Returns a target based on the specified class.
*
* @param targetClass the target class.
* @param the target object type.
* @return the invocation target.
*/
@NotNull
public static InvocationTarget classOfType(@NotNull final Class targetClass) {
return new ClassInvocationTarget(targetClass);
}
/**
* Returns a target based on the specified instance.
*
* @param target the target instance.
* @param the target object type.
* @return the invocation target.
*/
@NotNull
public static InvocationTarget instance(@NotNull final TYPE target) {
return new InstanceInvocationTarget(target);
}
/**
* Returns the target of the invocation.
*
* @return the target.
*/
@Nullable
public abstract Object getTarget();
/**
* Returns the target class.
*
* @return the target class.
*/
@NotNull
public abstract Class extends TYPE> getTargetClass();
/**
* Checks if this invocation target is assignable to the specified class.
*
* @param otherClass the other class.
* @return whether the invocation target is assignable to the class.
*/
public abstract boolean isAssignableTo(@NotNull Class> otherClass);
/**
* Checks if this invocation target is of the specified type.
*
* @param type the type class.
* @return whether the invocation target is of the specified type.
*/
public abstract boolean isOfType(@NotNull Class> type);
/**
* Invocation target wrapping a class.
*
* @param the target object type.
*/
private static class ClassInvocationTarget extends InvocationTarget {
private final Class mTargetClass;
/**
* Constructor.
*
* @param targetClass the target class.
*/
private ClassInvocationTarget(@NotNull final Class targetClass) {
mTargetClass = ConstantConditions.notNull("target class", targetClass);
}
@Nullable
@Override
public Object getTarget() {
return mTargetClass;
}
@Override
public int hashCode() {
return mTargetClass.hashCode();
}
@Override
public boolean isOfType(@NotNull final Class> type) {
return (mTargetClass == type);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
final ClassInvocationTarget that = (ClassInvocationTarget) o;
return mTargetClass.equals(that.mTargetClass);
}
@NotNull
@Override
public Class extends TYPE> getTargetClass() {
return mTargetClass;
}
@Override
public boolean isAssignableTo(@NotNull final Class> otherClass) {
return otherClass.isAssignableFrom(mTargetClass);
}
}
/**
* Invocation target wrapping an object instance.
*
* @param the target object type.
*/
private static class InstanceInvocationTarget extends InvocationTarget {
private final WeakReference mTarget;
private final Class extends TYPE> mTargetClass;
/**
* Constructor.
*
* @param target the target instance.
*/
@SuppressWarnings("unchecked")
private InstanceInvocationTarget(@NotNull final TYPE target) {
mTarget = new WeakReference(target);
mTargetClass = (Class extends TYPE>) target.getClass();
}
@Override
public boolean isOfType(@NotNull final Class> type) {
return type.isInstance(mTarget.get());
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
final InstanceInvocationTarget that = (InstanceInvocationTarget) o;
final Object referent = mTarget.get();
return (referent != null) && referent.equals(that.mTarget.get()) && mTargetClass.equals(
that.mTargetClass);
}
@Override
public int hashCode() {
final Object referent = mTarget.get();
int result = (referent != null) ? referent.hashCode() : 0;
result = 31 * result + mTargetClass.hashCode();
return result;
}
@Nullable
@Override
public Object getTarget() {
return mTarget.get();
}
@NotNull
@Override
public Class extends TYPE> getTargetClass() {
return mTargetClass;
}
@Override
public boolean isAssignableTo(@NotNull final Class> otherClass) {
return otherClass.isInstance(mTarget.get());
}
}
}