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

io.github.pustike.inject.BindingKey Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2016-2018 the original author or authors.
 *
 * 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
 *
 * https://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 io.github.pustike.inject;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Objects;
import jakarta.inject.Named;
import jakarta.inject.Provider;

import io.github.pustike.inject.utils.AnnotationUtils;

/**
 * Binding key that contains an injection type and an optional qualifier annotation. It is also used to match the type
 * and qualifier annotation at the point of injection.
 * @param  the type of the class specified in this key
 */
public final class BindingKey {
    // the injection type
    private final Class type;
    // qualifier annotation
    private final Annotation annotation;
    // type of qualifier annotation
    private final Class annotationType;
    // indicates that this key matches to a provider of the type
    private boolean providerKey;
    // indicates that this key matches to a List of the type
    private boolean multiBinding;
    // hash code of this binding key, computed lazily using all specified parameters
    private int hashCode;

    /**
     * Constructs a new Binding Key for the specified type, the qualifier annotation and annotation type.
     * @param type           the injection class
     * @param annotation     the qualifying annotation defined for the type
     * @param annotationType the type of qualifier annotation defined for the type
     */
    private BindingKey(Class type, Annotation annotation, Class annotationType) {
        this.type = Objects.requireNonNull(type);
        this.annotation = annotation;
        this.annotationType = annotationType;
    }

    /**
     * Constructs a new Binding Key for the specified type.
     * @param type the injection class
     * @param   the type of of the class modeled by this key
     * @return a new key with the specified type and no qualifying annotation
     */
    public static  BindingKey of(Class type) {
        return new BindingKey<>(type, null, null);
    }

    /**
     * Constructs a new Binding Key for the specified type and name.
     * @param type  the injection class
     * @param named the qualifying name defined for the type
     * @param    the type of of the class modeled by this key
     * @return a new key with the specified type and the named qualifier
     */
    public static  BindingKey of(Class type, String named) {
        return new BindingKey<>(type, Names.named(named), null);
    }

    /**
     * Constructs a new Binding Key for the specified type and the qualifier annotation.
     * @param type       the injection class
     * @param annotation the qualifying annotation defined for the type
     * @param         the type of of the class modeled by this key
     * @return a new key with the specified type and the qualifier annotation
     */
    public static  BindingKey of(Class type, Annotation annotation) {
        return new BindingKey<>(type, annotation, annotation == null ? null : annotation.annotationType());
    }

    /**
     * Constructs a new Binding Key for the specified type and the qualifier annotation.
     * @param type           the injection class
     * @param annotationType the type of qualifier annotation defined for the type
     * @param             the type of of the class modeled by this key
     * @return a new key with the specified type and the type of qualifier annotation
     */
    public static  BindingKey of(Class type, Class annotationType) {
        return new BindingKey<>(type, null, annotationType);
    }

    /**
     * Get the injection type of this key.
     * @return the injection type of this key
     */
    public Class getType() {
        return type;
    }

    /**
     * Create a new key to indicate that this key matches to a {@link jakarta.inject.Provider} of the type.
     * 

* Note: this key can only be used to get the instance from Injector, but not during binding. * @return a new key that matches to the provider of this binding type and qualifier */ public BindingKey> toProviderType() { return createBindingKey(true, multiBinding); } /** * Create a new key to indicate that this key matches to a {@link java.util.List} or {@link java.util.Collection} * of the given type bound using {@link io.github.pustike.inject.bind.MultiBinder}. *

* Note: this key can only be used to get the instance from Injector, but not during binding. * @return a new key that matches to the type bound using multiBinder */ public BindingKey> toListType() { return createBindingKey(providerKey, true); } /** * Create a new key to indicate that this key matches to a {@code List>} * of the given type bound using {@link io.github.pustike.inject.bind.MultiBinder}. *

* Note: this key can only be used to get the instance from Injector, but not during binding. * @return a new key that matches to the type bound using multiBinder */ public BindingKey>> toListProviderType() { return createBindingKey(true, true); } @SuppressWarnings("unchecked") private BindingKey createBindingKey(boolean isProviderKey, boolean isMultiBinding) { BindingKey bindingKey = new BindingKey<>(type, annotation, annotationType); bindingKey.providerKey = isProviderKey; bindingKey.multiBinding = isMultiBinding; bindingKey.hashCode = 0; return (BindingKey) bindingKey; } /** * Returns true if this key is of {@link jakarta.inject.Provider} type. * @return true if this key is of provider type. */ public boolean isProviderKey() { return providerKey; } /** * Uses the computed hash code of this key to check if the given object equals. * @param obj the reference object with which to compare * @return {@code true} if this object is the same as the obj argument; {@code false} otherwise * @see #hashCode() */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof BindingKey)) { return false; } BindingKey other = (BindingKey) obj; return hashCode() == other.hashCode(); } /** * Computes the hash code using hash codes of the binding type and qualifier annotation or annotation type. * @return the hash code value for this key */ @Override public int hashCode() { return hashCode == 0 ? hashCode = computeHashCode() : hashCode; } /** * Computes the hash code for this key. */ private int computeHashCode() { int result = type.hashCode(); if (annotation != null) { result = 31 * result + annotation.hashCode(); } else if (annotationType != null) { result = 31 * result + AnnotationUtils.hashCode(annotationType); } return multiBinding ? 31 * result + Boolean.hashCode(true) : result; } /** * Generates a string representation of the key using the binding type and qualifier annotation. * @return a string representation of the binding key */ @Override public String toString() { return toString(this); } private static String toString(BindingKey key) { String typeName = key.type.getName(); typeName = key.providerKey ? "Provider<" + typeName + '>' : typeName; typeName = key.multiBinding ? "List<" + typeName + '>' : typeName; StringBuilder sb = new StringBuilder(typeName); Annotation annotation = key.annotation; if (annotation != null) { if (annotation instanceof Named) { sb.append(" @Named(\"").append(((Named) annotation).value()).append("\")"); } else { sb.append(" @").append(annotation.annotationType().getName()); } } else if (key.annotationType != null) { sb.append(" @").append(key.annotationType.getName()); } return sb.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy