All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javabits.yar.Ids Maven / Gradle / Ivy

The newest version!
package org.javabits.yar;

import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import static java.util.Objects.requireNonNull;
import static org.javabits.yar.Annotations.checkRuntimeRetention;

/**
 * This class provides utility methods to construct and deal with {@link Id}.
 * This class provide 3 main ways to build {@code Id}:
 * 
    *
  • from {@code Class}
  • *
  • from {@code TypeToken}
  • *
  • from {@code Type}
  • *
* As follow: *

Class based construction:

*
 *     Ids.newId(MyInterface.class);
 *     Ids.newId(MyInterface.class, MyAnnotation.class);
 *     Ids.newId(MyInterface.class, Names.named("my-name"));
 * 
*

TypeToken based construction:

*
 *     Ids.newId(new TypeToken>(){});
 *     Ids.newId(new TypeToken>(){}, MyAnnotation.class);
 *     Ids.newId(new TypeToken>(){}, Names.named("my-name"));
 * 
*

Type based construction

*
 *     Ids.newId(aMethod.getGenericParameterTypes()[0]);
 *     Ids.newId(aMethod.getGenericParameterTypes()[0], MyAnnotation.class);
 *     Ids.newId(aMethod.getGenericParameterTypes()[0], Names.named("my-name"));
 * 
* * @author Romain Gilles */ public final class Ids { private Ids() { throw new AssertionError("Not for you!"); } /** * Returns a new {@link Id} for the given type. * * @param type the {@code Type} from which the {@code Id} must be constructed. * @param the type of the Id. * @return an new {@code Id} based on the given type. */ @SuppressWarnings("unchecked") public static Id newId(final Class type) { return (Id) newId((Type) type); } /** * Returns a new {@link Id} which represents the {@code type} qualified by * the {@code annotationClass}. * * @param type the type to which the new id has to be associated. * @param annotationClass the qualifying annotation type. * @param the type of the id. * @return an new {@code Id} based on the given type and annotation type. */ @SuppressWarnings("unchecked") public static Id newId(final Class type, final Class annotationClass) { return (Id) newId((Type) type, annotationClass); } /** * Returns a new {@link Id} which represents the {@code type} qualified by * the {@code annotation} instance. * * @param type the type to which the new id has to be associated. * @param annotation the qualifying annotation. * @param the type of the id. * @return an new {@code Id} based on the given type and annotation. */ @SuppressWarnings("unchecked") public static Id newId(final Class type, final Annotation annotation) { return (Id) newId((Type) type, annotation); } /** * Returns a new {@link Id} which represents the {@code type}. * * @param type the type to which the new id has to be associated. * @return an new {@code Id} based on the given type. */ public static Id newId(final Type type) { return IdImpl.newId(type); } /** * Returns a new {@link Id} which represents the {@code type} qualified by * the {@code annotationClass}. * * @param type the type to which the new id has to be associated. * @param annotationClass the qualifying annotation type. * @return an new {@code Id} based on the given type and annotation type. */ public static Id newId(final Type type, final Class annotationClass) { return IdImpl.newId(type, annotationClass); } /** * Returns a new {@link Id} which represents the {@code type} qualified by * the {@code annotation} instance. * * @param type the type to which the new id has to be associated. * @param annotation the qualifying annotation. * @return an new {@code Id} based on the given type and annotation. */ public static Id newId(final Type type, final Annotation annotation) { return IdImpl.newId(type, annotation); } static final class IdImpl implements Id { private final Type type; private final AnnotationStrategy annotationStrategy; private final int hashCode; private IdImpl(Type type, AnnotationStrategy annotationStrategy) { this.type = requireNonNull(type, "type"); this.annotationStrategy = requireNonNull(annotationStrategy, "annotationStrategy"); this.hashCode = computeHashCode(type, annotationStrategy); } private static Id newId(final Type type) { return new IdImpl<>(type, AbstractAnnotationStrategy.NULL_STRATEGY); } private static Id newId(final Type type, final Class annotationClass) { return new IdImpl<>(type, AbstractAnnotationStrategy.strategyFor(annotationClass)); } private static Id newId(final Type type, final Annotation annotation) { return new IdImpl<>(type, AbstractAnnotationStrategy.strategyFor(annotation)); } @Override public Type type() { return type; } @Override public Class annotationType() { return annotationStrategy.getAnnotationType(); } @Override public Annotation annotation() { return annotationStrategy.getAnnotation(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; IdImpl id = (IdImpl) o; return annotationStrategy.equals(id.annotationStrategy) && type.equals(id.type); } @Override public int hashCode() { return hashCode; } private int computeHashCode(Type type, AnnotationStrategy annotationStrategy) { int result = requireNonNull(type, "type").hashCode(); result = 31 * result + requireNonNull(annotationStrategy, "annotationStrategy").hashCode(); return result; } @Override public String toString() { return "Id[type=" + toString(type) + ", annotation=" + annotationStrategy + "]"; } static String toString(Type type) { return (type instanceof Class) ? ((Class) type).getName() : type.toString(); } interface AnnotationStrategy { @Nullable Annotation getAnnotation(); @Nullable Class getAnnotationType(); @Override int hashCode(); @Override boolean equals(Object o); } static abstract class AbstractAnnotationStrategy implements AnnotationStrategy { static final AnnotationStrategy NULL_STRATEGY = new NullAnnotationStrategy(); static AnnotationStrategy strategyFor(Class annotationClass) { return new TypeAnnotationStrategy(annotationClass); } public static AnnotationStrategy strategyFor(Annotation annotation) { if (Annotations.isMarker(annotation)) { return new TypeAnnotationStrategy(annotation.annotationType()); } return new InstanceAnnotationStrategy(annotation); } } static final class NullAnnotationStrategy extends AbstractAnnotationStrategy { NullAnnotationStrategy() { } @Nullable @Override public Annotation getAnnotation() { return null; } @Override public Class getAnnotationType() { return null; } @Override public String toString() { return "[none]"; } } static final class TypeAnnotationStrategy extends AbstractAnnotationStrategy { private final Class annotationClass; TypeAnnotationStrategy(Class annotationClass) { this.annotationClass = checkRuntimeRetention(annotationClass, "annotationClass"); } @Override public Annotation getAnnotation() { return null; } @Override public Class getAnnotationType() { return annotationClass; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TypeAnnotationStrategy that = (TypeAnnotationStrategy) o; return annotationClass.equals(that.annotationClass); } @Override public int hashCode() { return annotationClass.hashCode(); } @Override public String toString() { return "@" + annotationClass.toString(); } } static final class InstanceAnnotationStrategy extends AbstractAnnotationStrategy { private final Annotation annotation; InstanceAnnotationStrategy(Annotation annotation) { this.annotation = annotation; } @Nullable @Override public Annotation getAnnotation() { return annotation; } @Override public Class getAnnotationType() { return annotation.annotationType(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; InstanceAnnotationStrategy that = (InstanceAnnotationStrategy) o; return annotation.equals(that.annotation); } @Override public int hashCode() { return annotation.hashCode(); } @Override public String toString() { return annotation.toString(); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy