PropertyElementQuery.java
/*
* Copyright 2017-2022 original 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.micronaut.inject.ast;
import io.micronaut.context.annotation.BeanProperties;
import io.micronaut.core.annotation.AccessorsStyle;
import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.util.ArrayUtils;
import io.micronaut.core.util.CollectionUtils;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
/**
* Represents a query for {@link PropertyElement} definitions.
*
* @author Denis Stepanov
* @since 4.0.0
* @see PropertyElement
* @see ClassElement#getBeanProperties(PropertyElementQuery)
* @see BeanProperties
*/
public final class PropertyElementQuery {
private static final String[] DEFAULT_READ_PREFIXES = { AccessorsStyle.DEFAULT_READ_PREFIX };
private static final String[] DEFAULT_WRITE_PREFIXES = { AccessorsStyle.DEFAULT_WRITE_PREFIX };
private static final EnumSet<BeanProperties.AccessKind> DEFAULT_ACCESS_KINDS = EnumSet.of(BeanProperties.AccessKind.METHOD);
private BeanProperties.Visibility visibility = BeanProperties.Visibility.DEFAULT;
private Set<BeanProperties.AccessKind> accessKinds = DEFAULT_ACCESS_KINDS;
private Set<String> includes = Collections.emptySet();
private Set<String> excludes = Collections.emptySet();
private String[] readPrefixes = DEFAULT_READ_PREFIXES;
private String[] writePrefixes = DEFAULT_WRITE_PREFIXES;
private boolean allowSetterWithZeroArgs;
private boolean allowSetterWithMultipleArgs;
private boolean allowStaticProperties;
private boolean ignoreSettersWithDifferingType;
private Set<String> excludedAnnotations = Collections.emptySet();
/**
* Creates a query for the given metadata.
* @param annotationMetadata The metadata
* @return The query
*/
public static @NonNull PropertyElementQuery of(@NonNull AnnotationMetadata annotationMetadata) {
PropertyElementQuery conf = new PropertyElementQuery();
AnnotationValue<BeanProperties> annotation = annotationMetadata.getAnnotation(BeanProperties.class);
if (annotation != null) {
annotation.enumValue(BeanProperties.MEMBER_VISIBILITY, BeanProperties.Visibility.class)
.ifPresent(conf::visibility);
if (annotation.isPresent(BeanProperties.MEMBER_ACCESS_KIND)) {
conf.accessKinds(
annotation.enumValuesSet(BeanProperties.MEMBER_ACCESS_KIND, BeanProperties.AccessKind.class)
);
}
annotation.booleanValue(BeanProperties.MEMBER_ALLOW_WRITE_WITH_ZERO_ARGS)
.ifPresent(conf::allowSetterWithZeroArgs);
annotation.booleanValue(BeanProperties.MEMBER_ALLOW_WRITE_WITH_MULTIPLE_ARGS)
.ifPresent(conf::allowSetterWithMultipleArgs);
conf.includes(CollectionUtils.setOf(annotation.stringValues(BeanProperties.MEMBER_INCLUDES)));
conf.excludes(CollectionUtils.setOf(annotation.stringValues(BeanProperties.MEMBER_EXCLUDES)));
conf.excludedAnnotations(CollectionUtils.setOf(annotation.stringValues(BeanProperties.MEMBER_EXCLUDED_ANNOTATIONS)));
}
String[] readPrefixes = annotationMetadata.stringValues(AccessorsStyle.class, "readPrefixes");
if (ArrayUtils.isNotEmpty(readPrefixes)) {
conf.readPrefixes(readPrefixes);
}
String[] writerPrefixes = annotationMetadata.stringValues(AccessorsStyle.class, "writePrefixes");
if (ArrayUtils.isNotEmpty(writerPrefixes)) {
conf.writePrefixes(writerPrefixes);
}
return conf;
}
/**
* @return Whether to ignore setters that don't match the getter return type.
*/
public boolean isIgnoreSettersWithDifferingType() {
return ignoreSettersWithDifferingType;
}
/**
* Set whether to ignore setters that have a different receiver type to the getter return type.
* @param shouldIgnore True if they should be ignored.
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery ignoreSettersWithDifferingType(boolean shouldIgnore) {
this.ignoreSettersWithDifferingType = shouldIgnore;
return this;
}
/**
* @return The visibility strategy.
* @see io.micronaut.context.annotation.BeanProperties.Visibility
*/
@NonNull
public BeanProperties.Visibility getVisibility() {
return visibility;
}
/**
* Sets the visibility strategy.
* @param visibility The visibility strategy
* @return This PropertyElementQuery
* @see io.micronaut.context.annotation.BeanProperties.Visibility
*/
public @NonNull PropertyElementQuery visibility(BeanProperties.Visibility visibility) {
this.visibility = Objects.requireNonNullElse(visibility, BeanProperties.Visibility.DEFAULT);
return this;
}
/**
* The access kinds.
* @return A set of access kinds
* @see BeanProperties.AccessKind
*/
@NonNull
public Set<BeanProperties.AccessKind> getAccessKinds() {
return accessKinds;
}
/**
* Sets the access kinds.
* @param accessKinds The access kinds
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery accessKinds(@Nullable Set<BeanProperties.AccessKind> accessKinds) {
if (CollectionUtils.isNotEmpty(accessKinds)) {
this.accessKinds = Collections.unmodifiableSet(accessKinds);
} else {
this.accessKinds = DEFAULT_ACCESS_KINDS;
}
return this;
}
/**
* The property names to include.
* @return The includes.
*/
@NonNull
public Set<String> getIncludes() {
return includes;
}
/**
* Sets the property names to include.
* @param includes The includes
* @return This PropertyElementQuery
*/
@NonNull
public PropertyElementQuery includes(@Nullable Set<String> includes) {
if (CollectionUtils.isNotEmpty(includes)) {
this.includes = Collections.unmodifiableSet(includes);
} else {
this.includes = Collections.emptySet();
}
return this;
}
/**
* The property names to exclude.
* @return The excludes
*/
@NonNull
public Set<String> getExcludes() {
return excludes;
}
/**
* Sets the excluded property names.
* @param excludes The property names to exclude
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery excludes(@Nullable Set<String> excludes) {
if (CollectionUtils.isNotEmpty(excludes)) {
this.excludes = Collections.unmodifiableSet(excludes);
} else {
this.excludes = Collections.emptySet();
}
return this;
}
/**
* @return The read method prefixes.
*/
@NonNull
public String[] getReadPrefixes() {
return readPrefixes;
}
/**
* Sets the read method prefixes.
* @param readPrefixes The read methos prefixes
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery readPrefixes(String... readPrefixes) {
if (ArrayUtils.isNotEmpty(readPrefixes)) {
this.readPrefixes = readPrefixes;
} else {
this.readPrefixes = DEFAULT_READ_PREFIXES;
}
return this;
}
/**
* @return The write method prefixes.
*/
public @NonNull String[] getWritePrefixes() {
return writePrefixes;
}
/**
* Sets the write method prefixes.
* @param writePrefixes The write prefixes
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery writePrefixes(String[] writePrefixes) {
if (ArrayUtils.isNotEmpty(writePrefixes)) {
this.writePrefixes = writePrefixes;
} else {
this.writePrefixes = DEFAULT_WRITE_PREFIXES;
}
return this;
}
/**
* @return Whether to allow zero argument setters for boolean values etc.
*/
public boolean isAllowSetterWithZeroArgs() {
return allowSetterWithZeroArgs;
}
/**
* Sets whether to allow zero argument setters for boolean properties etc.
* @param allowSetterWithZeroArgs True to allow zero argument setters
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery allowSetterWithZeroArgs(boolean allowSetterWithZeroArgs) {
this.allowSetterWithZeroArgs = allowSetterWithZeroArgs;
return this;
}
/**
* Whether to allow setters with multiple arguments.
* @return True if setters with multiple arguments are allowed.
*/
public boolean isAllowSetterWithMultipleArgs() {
return allowSetterWithMultipleArgs;
}
/**
* Sets whether to allow setters with multiple arguments.
* @param allowSetterWithMultipleArgs True if setters with multiple arguments are allowed.
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery allowSetterWithMultipleArgs(boolean allowSetterWithMultipleArgs) {
this.allowSetterWithMultipleArgs = allowSetterWithMultipleArgs;
return this;
}
/**
* @return Whether to allow static properties.
*/
public boolean isAllowStaticProperties() {
return allowStaticProperties;
}
/**
* Sets whether to allow static properties.
* @param allowStaticProperties True if static properties are allowed.
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery allowStaticProperties(boolean allowStaticProperties) {
this.allowStaticProperties = allowStaticProperties;
return this;
}
/**
* @return The excludes annotation names.
*/
@NonNull
public Set<String> getExcludedAnnotations() {
return excludedAnnotations;
}
/**
* Sets the annotations names that should be used to indicate a property is excluded.
* @param excludedAnnotations The excluded annotation names
* @return This PropertyElementQuery
*/
public @NonNull PropertyElementQuery excludedAnnotations(@Nullable Set<String> excludedAnnotations) {
if (CollectionUtils.isNotEmpty(excludedAnnotations)) {
this.excludedAnnotations = Collections.unmodifiableSet(excludedAnnotations);
} else {
this.excludedAnnotations = Collections.emptySet();
}
return this;
}
}