Skip to content

Commit

Permalink
[OWB-1402] ensure Instance#select uses an append logic for qualifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
rmannibucau committed Feb 2, 2022
1 parent 8ccda93 commit 0da7a3c
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,19 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import javax.enterprise.context.spi.AlterableContext;
import javax.enterprise.context.spi.Context;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.util.TypeLiteral;
import javax.inject.Provider;

import org.apache.webbeans.annotation.DefaultLiteral;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.container.BeanManagerImpl;
import org.apache.webbeans.container.InjectionResolver;
Expand Down Expand Up @@ -178,14 +181,16 @@ public boolean isUnsatisfied()
* {@inheritDoc}
*/
@Override
public Instance<T> select(Annotation... qualifiers)
public Instance<T> select(final Annotation... qualifiers)
{
if (strictValidation)
{
webBeansContext.getAnnotationManager().checkQualifierConditions(qualifiers);
}

Annotation[] newQualifiersArray = qualifiers;
final Annotation[] newQualifiersArray = qualifiers.length == 0?
qualifierAnnotations.toArray(new Annotation[0]) :
concatenateQualifiers(qualifiers);
return new InstanceImpl<>(
injectionClazz, injectionPoint == null ? null : new InstanceInjectionPoint(injectionPoint, newQualifiersArray),
webBeansContext, newQualifiersArray);
Expand All @@ -203,19 +208,14 @@ public <U extends T> Instance<U> select(Class<U> subtype, Annotation... qualifie
}

Type sub = subtype;

if(sub == null)
{
sub = injectionClazz;
}
if (qualifiers== null || qualifiers.length == 0)
{

}
Annotation[] effectiveQualifiers = qualifiers != null && qualifiers.length > 0
? qualifiers
: qualifierAnnotations.toArray(new Annotation[qualifierAnnotations.size()]);

final Annotation[] effectiveQualifiers = qualifiers != null && qualifiers.length > 0
? concatenateQualifiers(qualifiers)
: qualifierAnnotations.toArray(new Annotation[0]);
return new InstanceImpl<>(sub, injectionPoint, webBeansContext, effectiveQualifiers);
}

Expand Down Expand Up @@ -250,6 +250,18 @@ public T next()
};
}

private Annotation[] concatenateQualifiers(final Annotation[] additionalQualifiers)
{
return Stream.concat(
qualifierAnnotations.stream()
.filter(it -> it.annotationType() != Any.class) // no more relevant if there is another one
// see org.apache.webbeans.portable.InstanceProducer.produce
// NOT equals() to respect user request but ==
.filter(it -> it != DefaultLiteral.INSTANCE),
Stream.of(additionalQualifiers))
.toArray(Annotation[]::new);
}

public void destroy(T instance)
{
if (instance == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void checkQualfiers() {
Factory.class), Collections.<String>emptyList(), true);

assertNotNull(instance1.select(new AnnotationLiteral<Qualifier1>() {}).get());
assertEquals(1, holder.getQualifiers().size());
assertEquals(holder.getQualifiers().toString(), 1, holder.getQualifiers().size());
assertEquals(Qualifier1.class, holder.getQualifiers().iterator().next().annotationType());

assertNotNull(instance2.select(AnyLiteral.INSTANCE).get());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.webbeans.test.instance;

import org.apache.webbeans.test.AbstractUnitTest;
import org.junit.Before;
import org.junit.Test;

import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Inject;
import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Collection;
import java.util.stream.Stream;

import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class InstanceSelectTest extends AbstractUnitTest {
@Inject
@Any
private Instance<Food> allTypesOfFood;

@Before
public void init() {
startContainer(asList(Cherry.class, Strawberry.class), emptyList(), true);
}

@Test
public void findYummyFruit() {
final Instance<Food> fruits = allTypesOfFood.select(new LiteralFoodType(FoodType.FRUIT));
final Instance<Food> jummyFruits = fruits.select(new LiteralTasteType(TasteType.JUMMY));
assertTrue(jummyFruits.stream().findAny().isPresent());
}

@Test
public void thereIsNoJummyVegetable() {
final Instance<Food> vegetables = allTypesOfFood.select(new LiteralFoodType(FoodType.VEGETABLE));
assertTrue(vegetables.isUnsatisfied());

final Instance<Food> jummyVegetables = vegetables.select(new LiteralTasteType(TasteType.JUMMY));
final Collection<Food> selected = jummyVegetables.stream().collect(toList());
assertFalse(selected.toString(), selected.stream().findAny().isPresent());
}

public static class LiteralTasteType extends AnnotationLiteral<TasteQualifier> implements TasteQualifier {
private final TasteType taste;

public LiteralTasteType(TasteType taste) {
this.taste = taste;
}

@Override
public TasteType value() {
return taste;
}
}

public static class LiteralFoodType extends AnnotationLiteral<FoodQualifier> implements FoodQualifier {
private final FoodType food;

public LiteralFoodType(FoodType food) {
this.food = food;
}

@Override
public FoodType value() {
return food;
}
}

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD, CONSTRUCTOR, PARAMETER})
public @interface FoodQualifier {
FoodType value();
}

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD, CONSTRUCTOR, PARAMETER})
public @interface TasteQualifier {
TasteType value();
}

public enum TasteType {
JUMMY,
DISGUSTING
}

public enum FoodType {
VEGETABLE,
FRUIT
}

@FoodQualifier(FoodType.FRUIT)
@TasteQualifier(TasteType.DISGUSTING)
public static class Cherry extends Food {
public Cherry() {
super("Cherry");
}
}

@FoodQualifier(FoodType.FRUIT)
@TasteQualifier(TasteType.JUMMY)
public static class Strawberry extends Food {
public Strawberry() {
super("Strawberry");
}
}

public static abstract class Food {
private final String name;

protected Food(String name) {
this.name = name;
}
}
}

0 comments on commit 0da7a3c

Please sign in to comment.