iterator() {
return new Iterator<>() {
int i = -1;
@Override
public boolean hasNext() {
return i + 1 < indexed.length;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
int index = indexed[++i];
return array[index];
}
};
}
@Override
public int size() {
return indexed.length;
}
}
/**
* Implementation of {@link UnsafeBeanProperty} that is using {@link BeanPropertyRef} and method dispatch.
*
* @param The property type
*/
private final class BeanPropertyImpl
implements UnsafeBeanProperty {
private final BeanPropertyRef
ref;
private final Class> typeOrWrapperType;
private final AnnotationMetadata annotationMetadata;
private BeanPropertyImpl(BeanPropertyRef
ref) {
this.ref = ref;
this.typeOrWrapperType = ReflectionUtils.getWrapperType(getType());
this.annotationMetadata = EvaluatedAnnotationMetadata.wrapIfNecessary(ref.argument.getAnnotationMetadata());
}
@NonNull
@Override
public String getName() {
return ref.argument.getName();
}
@NonNull
@Override
public Class
getType() {
return ref.argument.getType();
}
@Override
@NonNull
public Argument
asArgument() {
return ref.argument;
}
@NonNull
@Override
public BeanIntrospection getDeclaringBean() {
return AbstractInitializableBeanIntrospection.this;
}
@Override
public AnnotationMetadata getAnnotationMetadata() {
return annotationMetadata;
}
@Nullable
@Override
public P get(@NonNull B bean) {
ArgumentUtils.requireNonNull("bean", bean);
if (!beanType.isInstance(bean)) {
throw new IllegalArgumentException("Invalid bean [" + bean + "] for type: " + beanType);
}
if (isWriteOnly()) {
throw new UnsupportedOperationException("Cannot read from a write-only property: " + getName());
}
return dispatchOne(ref.getMethodIndex, bean, null);
}
@Override
public P getUnsafe(B bean) {
return dispatchOne(ref.getMethodIndex, bean, null);
}
@Override
public void set(@NonNull B bean, @Nullable P value) {
ArgumentUtils.requireNonNull("bean", bean);
if (!beanType.isInstance(bean)) {
throw new IllegalArgumentException("Invalid bean [" + bean + "] for type: " + beanType);
}
if (isReadOnly()) {
throw new UnsupportedOperationException("Cannot write a read-only property: " + getName());
}
if (value != null && !typeOrWrapperType.isInstance(value)) {
throw new IllegalArgumentException("Specified value [" + value + "] is not of the correct type: " + getType());
}
dispatchOne(ref.setMethodIndex, bean, value);
}
@Override
public void setUnsafe(B bean, P value) {
dispatchOne(ref.setMethodIndex, bean, value);
}
@Override
public B withValue(@NonNull B bean, @Nullable P value) {
ArgumentUtils.requireNonNull("bean", bean);
if (!beanType.isInstance(bean)) {
throw new IllegalArgumentException("Invalid bean [" + bean + "] for type: " + beanType);
}
return withValueUnsafe(bean, value);
}
@Override
public B withValueUnsafe(B bean, P value) {
if (value == getUnsafe(bean)) {
return bean;
} else if (ref.withMethodIndex == -1) {
if (!ref.readyOnly && ref.setMethodIndex != -1) {
dispatchOne(ref.setMethodIndex, bean, value);
return bean;
}
return UnsafeBeanProperty.super.withValue(bean, value);
} else {
return dispatchOne(ref.withMethodIndex, bean, value);
}
}
@Override
public boolean isReadOnly() {
return ref.readyOnly;
}
@Override
public boolean isWriteOnly() {
return ref.writeOnly;
}
@Override
public boolean hasSetterOrConstructorArgument() {
return ref.mutable;
}
@Override
public String toString() {
return "BeanProperty{" +
"beanType=" + beanType +
", type=" + ref.argument.getType() +
", name='" + ref.argument.getName() + '\'' +
'}';
}
}
/**
* Implementation of {@link UnsafeBeanWriteProperty} that is using {@link BeanPropertyRef} and method dispatch.
*
* @param
The property type
*/
private final class BeanWritePropertyImpl
implements UnsafeBeanWriteProperty {
private final Argument
argument;
private final Class> typeOrWrapperType;
private final AnnotationMetadata annotationMetadata;
private final int setMethodIndex;
private final int withMethodIndex;
private BeanWritePropertyImpl(BeanPropertyRef
ref) {
this.argument = ref.writeArgument;
this.typeOrWrapperType = ReflectionUtils.getWrapperType(getType());
this.annotationMetadata = EvaluatedAnnotationMetadata.wrapIfNecessary(argument.getAnnotationMetadata());
this.setMethodIndex = ref.setMethodIndex;
this.withMethodIndex = ref.withMethodIndex;
}
@NonNull
@Override
public String getName() {
return argument.getName();
}
@NonNull
@Override
public Class
getType() {
return argument.getType();
}
@Override
@NonNull
public Argument
asArgument() {
return argument;
}
@NonNull
@Override
public BeanIntrospection getDeclaringBean() {
return AbstractInitializableBeanIntrospection.this;
}
@Override
public AnnotationMetadata getAnnotationMetadata() {
return annotationMetadata;
}
@Override
public void set(@NonNull B bean, @Nullable P value) {
ArgumentUtils.requireNonNull("bean", bean);
if (!beanType.isInstance(bean)) {
throw new IllegalArgumentException("Invalid bean [" + bean + "] for type: " + bean);
}
if (value != null && !typeOrWrapperType.isInstance(value)) {
throw new IllegalArgumentException("Specified value [" + value + "] is not of the correct type: " + getType());
}
dispatchOne(setMethodIndex, bean, value);
}
@Override
public void setUnsafe(B bean, P value) {
dispatchOne(setMethodIndex, bean, value);
}
@Override
public B withValue(@NonNull B bean, @Nullable P value) {
ArgumentUtils.requireNonNull("bean", bean);
if (!beanType.isInstance(bean)) {
throw new IllegalArgumentException("Invalid bean [" + bean + "] for type: " + beanType);
}
return withValueUnsafe(bean, value);
}
@Override
public B withValueUnsafe(B bean, P value) {
if (withMethodIndex == -1) {
dispatchOne(setMethodIndex, bean, value);
return bean;
} else {
return dispatchOne(withMethodIndex, bean, value);
}
}
@Override
public String toString() {
return "BeanWriteProperty{" +
"beanType=" + beanType +
", type=" + argument.getType() +
", name='" + argument.getName() + '\'' +
'}';
}
}
/**
* Implementation of {@link io.micronaut.core.beans.UnsafeBeanReadProperty} that is using {@link BeanPropertyRef} and method dispatch.
*
* @param
The property type
*/
private final class BeanReadPropertyImpl
implements UnsafeBeanReadProperty {
private final Argument
argument;
private final AnnotationMetadata annotationMetadata;
private final int getMethodIndex;
private BeanReadPropertyImpl(BeanPropertyRef
ref) {
this.argument = ref.readArgument;
this.annotationMetadata = EvaluatedAnnotationMetadata.wrapIfNecessary(argument.getAnnotationMetadata());
this.getMethodIndex = ref.getMethodIndex;
}
@NonNull
@Override
public String getName() {
return argument.getName();
}
@NonNull
@Override
public Class
getType() {
return argument.getType();
}
@Override
@NonNull
public Argument
asArgument() {
return argument;
}
@NonNull
@Override
public BeanIntrospection getDeclaringBean() {
return AbstractInitializableBeanIntrospection.this;
}
@Override
public AnnotationMetadata getAnnotationMetadata() {
return annotationMetadata;
}
@Nullable
@Override
public P get(@NonNull B bean) {
ArgumentUtils.requireNonNull("bean", bean);
if (!beanType.isInstance(bean)) {
throw new IllegalArgumentException("Invalid bean [" + bean + "] for type: " + beanType);
}
return dispatchOne(getMethodIndex, bean, null);
}
@Override
public P getUnsafe(B bean) {
return dispatchOne(getMethodIndex, bean, null);
}
@Override
public String toString() {
return "BeanReadProperty{" +
"beanType=" + beanType +
", type=" + argument.getType() +
", name='" + argument.getName() + '\'' +
'}';
}
}
/**
* Implementation of {@link BeanMethod} that is using {@link BeanMethodRef} and method dispatch.
*
* @param
The property type
*/
private final class BeanMethodImpl
implements BeanMethod, ExecutableMethod {
private final BeanMethodRef
ref;
private BeanMethodImpl(BeanMethodRef
ref) {
this.ref = ref;
}
@NonNull
@Override
public BeanIntrospection getDeclaringBean() {
return AbstractInitializableBeanIntrospection.this;
}
@Override
public @NonNull
ReturnType
getReturnType() {
//noinspection unchecked
return new ReturnType() {
@Override
public Class
getType() {
return ref.returnType.getType();
}
@Override
@NonNull
public Argument
asArgument() {
return ref.returnType;
}
@Override
public Map> getTypeVariables() {
return ref.returnType.getTypeVariables();
}
@NonNull
@Override
public AnnotationMetadata getAnnotationMetadata() {
return EvaluatedAnnotationMetadata.wrapIfNecessary(ref.returnType.getAnnotationMetadata());
}
};
}
@NonNull
@Override
public AnnotationMetadata getAnnotationMetadata() {
return ref.annotationMetadata == null ? AnnotationMetadata.EMPTY_METADATA : ref.annotationMetadata;
}
@NonNull
@Override
public String getName() {
return ref.name;
}
@Override
public Argument>[] getArguments() {
return ref.arguments == null ? Argument.ZERO_ARGUMENTS : ref.arguments;
}
@Override
public P invoke(@NonNull B instance, Object... arguments) {
return dispatch(ref.methodIndex, instance, arguments);
}
@Override
public Method getTargetMethod() {
if (ClassUtils.REFLECTION_LOGGER.isWarnEnabled()) {
ClassUtils.REFLECTION_LOGGER.warn("Using getTargetMethod for method {} on type {} requires the use of reflection. GraalVM configuration necessary", getName(), getDeclaringType());
}
return getTargetMethodByIndex(ref.methodIndex);
}
@Override
public Class getDeclaringType() {
return getDeclaringBean().getBeanType();
}
@Override
public String getMethodName() {
return getName();
}
}
/**
* Bean property compile-time data container.
*
* @param The property type.
*/
@Internal
@UsedByGeneratedCode
public static final class BeanPropertyRef
{
@NonNull
final Argument
argument;
final int getMethodIndex;
final int setMethodIndex;
final int withMethodIndex;
final boolean readyOnly;
final boolean mutable;
final boolean writeOnly;
@Nullable
final Argument
readArgument;
@Nullable
final Argument
writeArgument;
public BeanPropertyRef(@NonNull Argument
argument,
int getMethodIndex,
int setMethodIndex,
int withMethodIndex,
boolean readyOnly,
boolean mutable) {
this(argument, null, null, getMethodIndex, setMethodIndex, withMethodIndex, readyOnly, mutable);
}
public BeanPropertyRef(@NonNull Argument
argument,
@Nullable Argument
readArgument,
@Nullable Argument
writeArgument,
int getMethodIndex,
int setMethodIndex,
int withMethodIndex,
boolean readyOnly,
boolean mutable) {
this.argument = argument;
this.getMethodIndex = getMethodIndex;
this.setMethodIndex = setMethodIndex;
this.withMethodIndex = withMethodIndex;
this.readyOnly = readyOnly;
this.mutable = mutable;
this.writeOnly = getMethodIndex == -1 && (setMethodIndex != -1 || withMethodIndex != -1);
this.writeArgument = writeArgument == null && (setMethodIndex != -1 || withMethodIndex != -1) ? argument : writeArgument;
this.readArgument = readArgument == null && (getMethodIndex != -1) ? argument : readArgument;
}
}
/**
* Bean method compile-time data container.
*
* @param
The property type.
*/
@Internal
@UsedByGeneratedCode
public static final class BeanMethodRef
{
@NonNull
final Argument
returnType;
@NonNull
final String name;
@Nullable
final AnnotationMetadata annotationMetadata;
@Nullable
final Argument>[] arguments;
final int methodIndex;
public BeanMethodRef(@NonNull Argument
returnType,
@NonNull String name,
@Nullable AnnotationMetadata annotationMetadata,
@Nullable Argument>[] arguments,
int methodIndex) {
this.returnType = returnType;
this.name = name;
this.annotationMetadata = EvaluatedAnnotationMetadata.wrapIfNecessary(annotationMetadata);
this.arguments = arguments;
this.methodIndex = methodIndex;
}
}
}