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

org.springframework.data.redis.repository.cdi.CdiBean Maven / Gradle / Ivy

There is a newer version: 3.2.5
Show newest version
/*
 * Copyright 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
 *
 *      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 org.springframework.data.redis.repository.cdi;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Stereotype;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.PassivationCapable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * Base class for {@link Bean} wrappers.
 *
 * @author Mark Paluch
 * @author Christoph Strobl
 */
public abstract class CdiBean implements Bean, PassivationCapable {

	private static final Logger LOGGER = LoggerFactory.getLogger(CdiBean.class);

	protected final BeanManager beanManager;

	private final Set qualifiers;
	private final Set types;
	private final Class beanClass;
	private final String passivationId;

	/**
	 * Creates a new {@link CdiBean}.
	 *
	 * @param qualifiers must not be {@literal null}.
	 * @param beanClass has to be an interface must not be {@literal null}.
	 * @param beanManager the CDI {@link BeanManager}, must not be {@literal null}.
	 */
	public CdiBean(Set qualifiers, Class beanClass, BeanManager beanManager) {
		this(qualifiers, Collections. emptySet(), beanClass, beanManager);
	}

	/**
	 * Creates a new {@link CdiBean}.
	 *
	 * @param qualifiers must not be {@literal null}.
	 * @param types additional bean types, must not be {@literal null}.
	 * @param beanClass must not be {@literal null}.
	 * @param beanManager the CDI {@link BeanManager}, must not be {@literal null}.
	 */
	public CdiBean(Set qualifiers, Set types, Class beanClass, BeanManager beanManager) {

		Assert.notNull(qualifiers, "Qualifier annotations must not be null!");
		Assert.notNull(beanManager, "BeanManager must not be null!");
		Assert.notNull(types, "Types must not be null!");
		Assert.notNull(beanClass, "Bean class mast not be null!");

		this.qualifiers = qualifiers;
		this.types = types;
		this.beanClass = beanClass;
		this.beanManager = beanManager;
		this.passivationId = createPassivationId(qualifiers, beanClass);
	}

	/**
	 * Creates a unique identifier for the given repository type and the given annotations.
	 *
	 * @param qualifiers must not be {@literal null} or contain {@literal null} values.
	 * @param repositoryType must not be {@literal null}.
	 * @return
	 */
	private final String createPassivationId(Set qualifiers, Class repositoryType) {

		List qualifierNames = new ArrayList<>(qualifiers.size());

		for (Annotation qualifier : qualifiers) {
			qualifierNames.add(qualifier.annotationType().getName());
		}

		Collections.sort(qualifierNames);

		StringBuilder builder = new StringBuilder(StringUtils.collectionToDelimitedString(qualifierNames, ":"));
		builder.append(":").append(repositoryType.getName());

		return builder.toString();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#getTypes()
	 */
	public Set getTypes() {

		Set types = new HashSet<>();
		types.add(beanClass);
		types.addAll(Arrays.asList(beanClass.getInterfaces()));
		types.addAll(this.types);

		return types;
	}

	/**
	 * Returns an instance of the given {@link Bean} from the container.
	 *
	 * @param  the actual class type of the {@link Bean}.
	 * @param bean the {@link Bean} defining the instance to create.
	 * @param type the expected component type of the instance created from the {@link Bean}.
	 * @return an instance of the given {@link Bean}.
	 * @see javax.enterprise.inject.spi.BeanManager#getReference(Bean, Type, CreationalContext)
	 * @see javax.enterprise.inject.spi.Bean
	 * @see java.lang.reflect.Type
	 */
	@SuppressWarnings("unchecked")
	protected  S getDependencyInstance(Bean bean, Type type) {
		return (S) beanManager.getReference(bean, type, beanManager.createCreationalContext(bean));
	}

	/**
	 * Forces the initialization of bean target.
	 */
	public final void initialize() {
		create(beanManager.createCreationalContext(this));
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.context.spi.Contextual#destroy(java.lang.Object, javax.enterprise.context.spi.CreationalContext)
	 */
	public void destroy(T instance, CreationalContext creationalContext) {

		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug(String.format("Destroying bean instance %s for repository type '%s'.", instance.toString(),
					beanClass.getName()));
		}

		creationalContext.release();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#getQualifiers()
	 */
	public Set getQualifiers() {
		return qualifiers;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#getName()
	 */
	public String getName() {

		return getQualifiers().contains(Default.class) ? beanClass.getName()
				: beanClass.getName() + "-" + getQualifiers().toString();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#getStereotypes()
	 */
	public Set> getStereotypes() {

		Set> stereotypes = new HashSet<>();

		for (Annotation annotation : beanClass.getAnnotations()) {
			Class annotationType = annotation.annotationType();
			if (annotationType.isAnnotationPresent(Stereotype.class)) {
				stereotypes.add(annotationType);
			}
		}

		return stereotypes;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#getBeanClass()
	 */
	public Class getBeanClass() {
		return beanClass;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#isAlternative()
	 */
	public boolean isAlternative() {
		return beanClass.isAnnotationPresent(Alternative.class);
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#isNullable()
	 */
	public boolean isNullable() {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#getInjectionPoints()
	 */
	public Set getInjectionPoints() {
		return Collections.emptySet();
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.Bean#getScope()
	 */
	public Class getScope() {
		return ApplicationScoped.class;
	}

	/*
	 * (non-Javadoc)
	 * @see javax.enterprise.inject.spi.PassivationCapable#getId()
	 */
	public String getId() {
		return passivationId;
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String.format("CdiBean: type='%s', qualifiers=%s", beanClass.getName(), qualifiers.toString());
	}

}