Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.osgl.inject;
/*-
* #%L
* OSGL Genie
* %%
* Copyright (C) 2017 OSGL (Open Source General Library)
* %%
* 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.
* #L%
*/
import org.osgl.$;
import org.osgl.inject.annotation.*;
import org.osgl.inject.util.AnnotationUtil;
import org.osgl.inject.util.ParameterizedTypeImpl;
import org.osgl.util.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
/**
* Specification of a bean to be injected.
*/
public class BeanSpec implements BeanInfo {
/**
* The dependency injector.
*
* The injector can be used to do some check including
* the following:
*
* * {@link Injector#isQualifier(Class)}
* * {@link Injector#scopeByAlias(Class)}
*/
private final Injector injector;
/**
* Pre-calculated {@link Object#hashCode()} of this bean spec.
*/
private final int hc;
/**
* The {@link Type} of the bean.
*/
private final Type type;
/**
* The raw type of {@link #type()}
*/
private transient volatile Class> rawType;
/**
* The origin of this BeanSpec
*/
private Field field;
/**
* Is the bean an array type or not.
*/
private final boolean isArray;
private final Set elementLoaders = new HashSet<>();
private final Set filters = new HashSet<>();
private final Set transformers = new HashSet<>();
private final Set qualifiers = new HashSet<>();
private final Set postProcessors = new HashSet<>();
// only applied when bean spec constructed from Field
private final int modifiers;
/**
* The annotations will be used for calculating the hashCode and do
* equality test. The following annotations will added into
* the list:
* * {@link #elementLoaders}
* * {@link #filters}
* * {@link #qualifiers}
* * {@link #valueLoader}
* * {@link #postProcessors}
*/
private final Map, Annotation> annotations = new HashMap<>();
/**
* Stores all annotations including the ones that participating
* hashCode calculating and those who don't equality test.
*
* @see #annotations
*/
private final Map, Annotation> allAnnotations = new HashMap<>();
/**
* Stores all annotations that are tagged with another annotation mapped to the tag annotation class.
* E.g. for all annotation that are marked with `@Qualifier` will be stored in a set mapped to
* `Qualifier.class`
*/
private final Map, Set> tagAnnotations = new HashMap<>();
private final Set annoData = new HashSet<>();
private final Set injectTags = new HashSet<>();
/**
* Store the name value of Named annotation if presented.
*/
private String originalName;
private String name;
private MapKey mapKey;
private Class extends Annotation> scope;
private BeanSpec componentSpec;
private volatile boolean componentSpecSet;
private boolean stopInheritedScope;
private Annotation valueLoader;
private List typeParams;
// simple type without injection tag
private volatile Map fields;
/**
* Construct the `BeanSpec` with bean type and field or parameter
* annotations.
*
* @param type
* the type of the bean to be instantiated
* @param annotations
* the annotation tagged on field or parameter,
* or `null` if this is a direct API injection
* request
* @param name
* optional, the name coming from the Named qualifier
* @param injector
* the injector instance
* @param modifiers
* the modifiers
*/
private BeanSpec(Type type, Annotation[] annotations, String name, Injector injector, int modifiers) {
this(type, annotations, name, injector, modifiers, C.Map());
}
private BeanSpec(Type type, Annotation[] annotations, String name, Injector injector, int modifiers, Map typeParamImplLookup) {
this.injector = injector;
this.type = type;
this.originalName = name;
this.name = name;
this.rawType = rawTypeOf(type, typeParamImplLookup);
this.typeParams(typeParamImplLookup);
this.isArray = rawType.isArray();
this.resolveTypeAnnotations(injector);
this.resolveAnnotations(annotations, injector, typeParamImplLookup);
this.hc = calcHashCode();
this.modifiers = modifiers;
}
private BeanSpec(BeanSpec source, Type convertTo) {
this.originalName = source.name;
this.name = source.name;
this.injector = source.injector;
this.type = convertTo;
if (convertTo == ArrayList.class) {
this.rawType = ArrayList.class;
this.typeParams = (List)C.list(this.rawType);
}
this.isArray = rawType().isArray();
this.qualifiers.addAll(source.qualifiers);
this.elementLoaders.addAll(source.elementLoaders);
this.filters.addAll(source.filters);
this.transformers.addAll(source.transformers);
this.valueLoader = source.valueLoader;
this.annotations.putAll(source.annotations);
this.annoData.addAll(source.annoData);
this.allAnnotations.putAll(source.allAnnotations);
this.tagAnnotations.putAll(source.tagAnnotations);
this.hc = calcHashCode();
this.modifiers = source.modifiers;
}
private BeanSpec(BeanSpec source, String name) {
this.originalName = source.name;
this.name = name;
this.injector = source.injector;
this.type = source.type;
this.rawType = source.rawType;
this.isArray = source.isArray;
this.qualifiers.addAll(source.qualifiers);
this.elementLoaders.addAll(source.elementLoaders);
this.filters.addAll(source.filters);
this.transformers.addAll(source.transformers);
this.valueLoader = source.valueLoader;
this.annotations.putAll(source.annotations);
this.annoData.addAll(source.annoData);
this.allAnnotations.putAll(source.allAnnotations);
this.tagAnnotations.putAll(source.tagAnnotations);
this.hc = calcHashCode();
this.modifiers = source.modifiers;
this.rawType = source.rawType;
this.typeParams = source.typeParams;
}
@Override
public int hashCode() {
return hc;
}
/**
* A bean spec equals to another bean spec if all of the following conditions are met:
* * the {@link #type} of the two bean spec equals to each other
* * the {@link #annotations} of the two bean spec equals to each other
*
* Specifically, {@link #scope} does not participate comparison because
* 1. Scope annotations shall be put onto {@link java.lang.annotation.ElementType#TYPE type},
* or the factory method with {@link Provides} annotation, which is equivalent to `Type`.
* So it is safe to ignore scope annotation because one type cannot be annotated with different
* scope
* 2. If we count scope annotation in equality test, we will never be able to get the correct
* provider stem from the factory methods.
*
* @param obj the object to compare with this object
* @return `true` if the two objects equals as per described above
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof BeanSpec) {
BeanSpec that = (BeanSpec) obj;
return that.hc == hc
&& $.eq(type, that.type)
&& $.eq(name, that.name)
&& $.eq(annoData, that.annoData);
}
return false;
}
@Override
public String toString() {
StringBuilder sb = S.builder(type());
if (S.notBlank(name)) {
sb.append("(").append(name).append(")");
}
C.List