org.instancio.settings.Keys Maven / Gradle / Ivy
/*
* Copyright 2022-2024 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
*
* 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 org.instancio.settings;
import org.instancio.documentation.ExperimentalApi;
import org.instancio.generator.AfterGenerate;
import org.instancio.internal.settings.InternalKey;
import org.instancio.internal.settings.RangeAdjuster;
import org.instancio.settings.SettingKey.SettingKeyBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.instancio.internal.util.Constants.MAX_SIZE;
import static org.instancio.internal.util.Constants.MIN_SIZE;
import static org.instancio.internal.util.Constants.NUMERIC_MAX;
import static org.instancio.internal.util.Constants.NUMERIC_MIN;
/**
* Defines all keys supported by Instancio.
*
* @see SettingKey
* @see Settings
* @since 1.1.10
*/
public final class Keys {
private static final RangeAdjuster MIN_ADJUSTER = RangeAdjuster.MIN_ADJUSTER;
private static final RangeAdjuster MAX_ADJUSTER = RangeAdjuster.MAX_ADJUSTER;
private static final List> ALL_KEYS = new ArrayList<>();
/**
* Specifies whether to assign values using fields or methods;
* default is {@link AssignmentType#FIELD}; property name {@code assignment.type}.
*
* This setting does not apply to fields that are {@code final} and
* {@code record} classes, since those cannot have setters.
*
* @see AssignmentType
* @see #ON_SET_METHOD_ERROR
* @see #ON_SET_METHOD_NOT_FOUND
* @see #SETTER_EXCLUDE_MODIFIER
* @see #SETTER_STYLE
* @since 2.1.0
*/
@ExperimentalApi
public static final SettingKey ASSIGNMENT_TYPE = registerRequiredNonAdjustable(
"assignment.type", AssignmentType.class, AssignmentType.FIELD);
/**
* Specifies the default value of the {@link AfterGenerate} hint
* supplied from custom generators to the engine;
* default is {@link AfterGenerate#POPULATE_NULLS_AND_DEFAULT_PRIMITIVES};
* property name {@code hint.after.generate}.
*
* @see AfterGenerate
* @since 2.0.0
*/
public static final SettingKey AFTER_GENERATE_HINT = registerRequiredNonAdjustable(
"hint.after.generate", AfterGenerate.class, AfterGenerate.POPULATE_NULLS_AND_DEFAULT_PRIMITIVES);
/**
* Specifies whether a {@code null} can be generated for array elements;
* default is {@code false}; property name {@code array.elements.nullable}.
*/
public static final SettingKey ARRAY_ELEMENTS_NULLABLE = registerRequiredNonAdjustable(
"array.elements.nullable", Boolean.class, false);
/**
* Specifies minimum length for arrays;
* default is 2; property name {@code array.min.length}.
*/
public static final SettingKey ARRAY_MIN_LENGTH = registerRequiredAdjustable(
"array.min.length", Integer.class, MIN_SIZE, MIN_ADJUSTER, false);
/**
* Specifies maximum length for arrays;
* default is 6; property name {@code array.max.length}.
*/
public static final SettingKey ARRAY_MAX_LENGTH = registerRequiredAdjustable(
"array.max.length", Integer.class, MAX_SIZE, MAX_ADJUSTER, false);
/**
* Specifies whether a null can be generated for arrays;
* default is {@code false}; property name {@code array.nullable}.
*/
public static final SettingKey ARRAY_NULLABLE = registerRequiredNonAdjustable(
"array.nullable", Boolean.class, false);
/**
* Specifies whether values should be generated based on
* Jakarta Bean Validation 3.0
* annotations, if present;
* default is {@code false}; property name {@code bean.validation.api.enabled}.
*
* @see #BEAN_VALIDATION_TARGET
* @since 2.7.0
*/
@ExperimentalApi
public static final SettingKey BEAN_VALIDATION_ENABLED = registerRequiredNonAdjustable(
"bean.validation.enabled", Boolean.class, false);
/**
* Specifies whether Bean Validation annotations are declared on fields or getters;
* default is {@link BeanValidationTarget#FIELD}; property name {@code bean.validation.target}.
*
* @see #BEAN_VALIDATION_ENABLED
* @since 3.4.0
*/
@ExperimentalApi
public static final SettingKey BEAN_VALIDATION_TARGET = registerRequiredNonAdjustable(
"bean.validation.target", BeanValidationTarget.class, BeanValidationTarget.FIELD);
/**
* Specifies the {@code scale} for generating {@code BigDecimal};
* default is {@code 2}; property name {@code bigdecimal.scale}.
*
* @since 3.3.0
*/
@ExperimentalApi
public static final SettingKey BIG_DECIMAL_SCALE = registerRequiredNonAdjustable(
"bigdecimal.scale", Integer.class, 2);
/**
* Specifies whether a {@code null} can be generated for Boolean type;
* default is {@code false}; property name {@code boolean.nullable}.
*/
public static final SettingKey BOOLEAN_NULLABLE = registerRequiredNonAdjustable(
"boolean.nullable", Boolean.class, false);
/**
* Specifies minimum value for bytes;
* default is 1; property name {@code byte.min}.
*/
public static final SettingKey BYTE_MIN = registerRequiredAdjustable(
"byte.min", Byte.class, (byte) NUMERIC_MIN, MIN_ADJUSTER, true);
/**
* Specifies maximum value for bytes;
* default is 127; property name {@code byte.max}.
*/
public static final SettingKey BYTE_MAX = registerRequiredAdjustable(
"byte.max", Byte.class, (byte) 127, MAX_ADJUSTER, true);
/**
* Specifies whether a {@code null} can be generated for Byte type;
* default is {@code false}; property name {@code byte.nullable}.
*/
public static final SettingKey BYTE_NULLABLE = registerRequiredNonAdjustable(
"byte.nullable", Boolean.class, false);
/**
* Specifies whether a {@code null} can be generated for Character type;
* default is {@code false}; property name {@code character.nullable}.
*/
public static final SettingKey CHARACTER_NULLABLE = registerRequiredNonAdjustable(
"character.nullable", Boolean.class, false);
/**
* Specifies whether a {@code null} can be generated for collection elements;
* default is {@code false}; property name {@code collection.elements.nullable}.
*/
public static final SettingKey COLLECTION_ELEMENTS_NULLABLE = registerRequiredNonAdjustable(
"collection.elements.nullable", Boolean.class, false);
/**
* Specifies minimum size for collections;
* default is 2; property name {@code collection.min.size}.
*/
public static final SettingKey COLLECTION_MIN_SIZE = registerRequiredAdjustable(
"collection.min.size", Integer.class, MIN_SIZE, MIN_ADJUSTER, false);
/**
* Specifies maximum size for collections;
* default is 6; property name {@code collection.max.size}.
*/
public static final SettingKey COLLECTION_MAX_SIZE = registerRequiredAdjustable(
"collection.max.size", Integer.class, MAX_SIZE, MAX_ADJUSTER, false);
/**
* Specifies whether a {@code null} can be generated for collections;
* default is {@code false}; property name {@code collection.nullable}.
*/
public static final SettingKey COLLECTION_NULLABLE = registerRequiredNonAdjustable(
"collection.nullable", Boolean.class, false);
/**
* Specifies minimum value for doubles;
* default is 1; property name {@code double.min}.
*/
public static final SettingKey DOUBLE_MIN = registerRequiredAdjustable(
"double.min", Double.class, (double) NUMERIC_MIN, MIN_ADJUSTER, true);
/**
* Specifies maximum value for doubles;
* default is 10000; property name {@code double.max}.
*/
public static final SettingKey DOUBLE_MAX = registerRequiredAdjustable(
"double.max", Double.class, (double) NUMERIC_MAX, MAX_ADJUSTER, true);
/**
* Specifies whether a {@code null} can be generated for Double type;
* default is {@code false}; property name {@code double.nullable}.
*/
public static final SettingKey DOUBLE_NULLABLE = registerRequiredNonAdjustable(
"double.nullable", Boolean.class, false);
/**
* Specifies whether internal exceptions should be propagated up;
* default is {@code false}; property name {@code fail.on.error}.
*
* @since 3.0.1
*/
@ExperimentalApi
public static final SettingKey FAIL_ON_ERROR = registerRequiredNonAdjustable(
"fail.on.error", Boolean.class, false);
/**
* Specifies minimum value for floats;
* default is 1; property name {@code float.min}.
*/
public static final SettingKey FLOAT_MIN = registerRequiredAdjustable(
"float.min", Float.class, (float) NUMERIC_MIN, MIN_ADJUSTER, true);
/**
* Specifies maximum value for floats;
* default is 10000; property name {@code float.max}.
*/
public static final SettingKey FLOAT_MAX = registerRequiredAdjustable(
"float.max", Float.class, (float) NUMERIC_MAX, MAX_ADJUSTER, true);
/**
* Specifies whether a {@code null} can be generated for Float type;
* default is {@code false}; property name {@code float.nullable}.
*/
public static final SettingKey FLOAT_NULLABLE = registerRequiredNonAdjustable(
"float.nullable", Boolean.class, false);
/**
* Specifies minimum value for integers;
* default is 1; property name {@code integer.min}.
*/
public static final SettingKey INTEGER_MIN = registerRequiredAdjustable(
"integer.min", Integer.class, NUMERIC_MIN, MIN_ADJUSTER, true);
/**
* Specifies maximum value for integers;
* default is 10000; property name {@code integer.max}.
*/
public static final SettingKey INTEGER_MAX = registerRequiredAdjustable(
"integer.max", Integer.class, NUMERIC_MAX, MAX_ADJUSTER, true);
/**
* Specifies whether a {@code null} can be generated for Integer type;
* default is {@code false}; property name {@code integer.nullable}.
*/
public static final SettingKey INTEGER_NULLABLE = registerRequiredNonAdjustable(
"integer.nullable", Boolean.class, false);
/**
* Specifies whether values should be generated based on
* JPA annotations, such as {@code @Column.length};
* default is {@code false}; property name {@code jpa.enabled}.
*
* @since 3.3.0
*/
@ExperimentalApi
public static final SettingKey JPA_ENABLED = registerRequiredNonAdjustable(
"jpa.enabled", Boolean.class, false);
/**
* Specifies minimum value for longs;
* default is 1; property name {@code long.min}.
*/
public static final SettingKey LONG_MIN = registerRequiredAdjustable(
"long.min", Long.class, (long) NUMERIC_MIN, MIN_ADJUSTER, true);
/**
* Specifies maximum value for longs;
* default is 10000; property name {@code long.max}.
*/
public static final SettingKey LONG_MAX = registerRequiredAdjustable(
"long.max", Long.class, (long) NUMERIC_MAX, MAX_ADJUSTER, true);
/**
* Specifies whether a {@code null} can be generated for Long type;
* default is {@code false}; property name {@code long.nullable}.
*/
public static final SettingKey LONG_NULLABLE = registerRequiredNonAdjustable(
"long.nullable", Boolean.class, false);
/**
* Specifies whether a {@code null} can be generated for map keys;
* default is {@code false}; property name {@code map.keys.nullable}.
*/
public static final SettingKey MAP_KEYS_NULLABLE = registerRequiredNonAdjustable(
"map.keys.nullable", Boolean.class, false);
/**
* Specifies minimum size for maps;
* default is 2; property name {@code map.min.size}.
*/
public static final SettingKey MAP_MIN_SIZE = registerRequiredAdjustable(
"map.min.size", Integer.class, MIN_SIZE, MIN_ADJUSTER, false);
/**
* Specifies maximum size for maps;
* default is 6; property name {@code map.max.size}.
*/
public static final SettingKey MAP_MAX_SIZE = registerRequiredAdjustable(
"map.max.size", Integer.class, MAX_SIZE, MAX_ADJUSTER, false);
/**
* Specifies whether a {@code null} can be generated for maps;
* default is {@code false}; property name {@code map.nullable}.
*/
public static final SettingKey MAP_NULLABLE = registerRequiredNonAdjustable(
"map.nullable", Boolean.class, false);
/**
* Specifies whether a {@code null} can be generated for map values;
* default is {@code false}; property name {@code map.values.nullable}.
*/
public static final SettingKey MAP_VALUES_NULLABLE = registerRequiredNonAdjustable(
"map.values.nullable", Boolean.class, false);
/**
* Specifies the maximum depth of the generated object tree;
* default is {@code 8}; property name {@code max.depth}.
*
* @since 2.7.0
*/
public static final SettingKey MAX_DEPTH = registerRequiredNonAdjustable(
"max.depth", Integer.class, 8);
/**
* Specifies the mode: strict (unused selectors will trigger an exception) or lenient;
* default is {@link Mode#STRICT}; property name {@code mode}.
*
* @see Mode
* @since 1.3.3
*/
public static final SettingKey MODE = registerRequiredNonAdjustable("mode", Mode.class, Mode.STRICT);
/**
* Specifies what should happen if an error occurs setting a field's value;
* default is {@link OnSetFieldError#IGNORE}; property name {@code on.set.field.error}.
*
* Warning: an error caused by assigning an incompatible type is
* considered a user error and is never ignored, despite this setting.
*
* @see OnSetFieldError
* @since 2.1.0
*/
@ExperimentalApi
public static final SettingKey ON_SET_FIELD_ERROR = registerRequiredNonAdjustable(
"on.set.field.error", OnSetFieldError.class, OnSetFieldError.IGNORE);
/**
* Specifies what should happen if an error occurs invoking a setter;
* default is {@link OnSetMethodError#ASSIGN_FIELD}; property name {@code on.set.method.error}.
*
* @see OnSetMethodError
* @since 2.1.0
*/
@ExperimentalApi
public static final SettingKey ON_SET_METHOD_ERROR = registerRequiredNonAdjustable(
"on.set.method.error", OnSetMethodError.class, OnSetMethodError.ASSIGN_FIELD);
/**
* Specifies what should happen if a setter method for a field cannot be resolved;
* default is {@link OnSetMethodNotFound#ASSIGN_FIELD}; property name {@code on.set.method.not.found}.
*
* Warning: {@link OnSetMethodNotFound#FAIL} is not applied to {@code final} fields
* since a field declared as {@code final} cannot have a setter.
*
* @see OnSetMethodNotFound
* @see #ON_SET_METHOD_UNMATCHED
* @since 2.1.0
*/
@ExperimentalApi
public static final SettingKey ON_SET_METHOD_NOT_FOUND = registerRequiredNonAdjustable(
"on.set.method.not.found", OnSetMethodNotFound.class, OnSetMethodNotFound.ASSIGN_FIELD);
/**
* Specifies what should happen if a setter without a matching field is encountered;
* default is {@link OnSetMethodUnmatched#IGNORE}; property name {@code on.set.method.unmatched}.
*
* This setting is only applicable if {@link #ASSIGNMENT_TYPE}
* is set to {@link AssignmentType#METHOD}.
*
*
The matching of fields and setter methods is based on the configured
* {@link #SETTER_STYLE} setting.
*
* @see OnSetMethodUnmatched
* @see #ASSIGNMENT_TYPE
* @see #ON_SET_METHOD_NOT_FOUND
* @see #SETTER_STYLE
* @since 4.0.0
*/
@ExperimentalApi
public static final SettingKey ON_SET_METHOD_UNMATCHED = registerRequiredNonAdjustable(
"on.set.method.unmatched", OnSetMethodUnmatched.class, OnSetMethodUnmatched.IGNORE);
/**
* Specifies whether initialised fields are allowed to be overwritten;
* default is {@code true}; property name {@code overwrite.existing.values}.
*
* @since 2.0.0
*/
public static final SettingKey OVERWRITE_EXISTING_VALUES = registerRequiredNonAdjustable(
"overwrite.existing.values", Boolean.class, true);
/**
* Specifies the seed value;
* default is {@code null}; property name {@code seed}.
*
* @since 1.5.1
*/
public static final SettingKey SEED = registerOptionalNonAdjustable(
"seed", Long.class, null);
/**
* Specifies whether back references should be set for cyclic classes;
* default is {@code false} (cycles are terminated with {@code null});
* property name {@code set.back.references}.
*
* For example, given the following classes:
*
{@code
* class Order {
* List items;
* }
* class OrderItem {
* Order order;
* }
* }
*
* If {@code SET_BACK_REFERENCES} is disabled,
* creating an instance of {@code Order} would result in the
* {@code OrderItem.order} field being {@code null}:
*
*
{@code
* Order order = Instancio.create(Order.class);
*
* assertThat(order.getItems()).allSatisfy(item ->
* assertThat(item.getOrder()).isNull()
* );
* }
*
* If {@code SET_BACK_REFERENCES} is enabled,
* creating an instance of {@code Order} would result in the
* {@code OrderItem.order} field being set to the parent order:
*
*
{@code
* Settings settings = Settings.create().set(Keys.SET_BACK_REFERENCES, true);
* Order order = Instancio.of(Order.class)
* .withSettings(settings)
* .create();
*
* assertThat(order.getItems()).allSatisfy(item ->
* assertThat(item.getOrder()).isSameAs(order)
* );
* }
*
* @since 3.0.0
*/
@ExperimentalApi
public static final SettingKey SET_BACK_REFERENCES = registerRequiredNonAdjustable(
"set.back.references", Boolean.class, false);
/**
* Specifies modifier exclusions for setter-methods;
* default is {@code 0} (no exclusions);
* property name {@code setter.exclude.modifier}.
*
* This setting can be used to control which setter methods are allowed
* to be invoked (based on method modifiers) when {@link #ASSIGNMENT_TYPE}
* is set to {@link AssignmentType#METHOD}). For instance, using this
* setting, it is possible to restrict method assignment to {@code public}
* setters only (by default, a setter is invoked even if it is {@code private}).
*
*
Multiple modifiers can be specified using logical {@code OR}
* operator. For example, the following allows only {@code public} methods:
*
*
{@code
* int exclusions = MethodModifier.PACKAGE_PRIVATE
* | MethodModifier.PROTECTED
* | MethodModifier.PRIVATE;
*
* Settings.create().set(Keys.SETTER_EXCLUDE_MODIFIER, exclusions);
* }
*
* @see #ASSIGNMENT_TYPE
* @see MethodModifier
* @since 2.16.0
*/
@ExperimentalApi
public static final SettingKey SETTER_EXCLUDE_MODIFIER = registerRequiredNonAdjustable(
"setter.exclude.modifier", Integer.class, 0);
/**
* Indicates the naming convention of setter methods to use;
* default is {@link SetterStyle#SET}; property name {@code setter.style}.
*
* @see SetterStyle
* @since 2.1.0
*/
@ExperimentalApi
public static final SettingKey SETTER_STYLE = registerRequiredNonAdjustable(
"setter.style", SetterStyle.class, SetterStyle.SET);
/**
* Specifies minimum value for shorts;
* default is 1; property name {@code short.min}.
*/
public static final SettingKey SHORT_MIN = registerRequiredAdjustable(
"short.min", Short.class, (short) 1, MIN_ADJUSTER, true);
/**
* Specifies maximum value for shorts;
* default is 10000; property name {@code short.max}.
*/
public static final SettingKey SHORT_MAX = registerRequiredAdjustable(
"short.max", Short.class, (short) NUMERIC_MAX, MAX_ADJUSTER, true);
/**
* Specifies whether a {@code null} can be generated for Short type;
* default is {@code false}; property name {@code short.nullable}.
*/
public static final SettingKey SHORT_NULLABLE = registerRequiredNonAdjustable(
"short.nullable", Boolean.class, false);
/**
* Specifies whether an empty string can be generated;
* default is {@code false}; property name {@code string.allow.empty}.
*/
public static final SettingKey STRING_ALLOW_EMPTY = registerRequiredNonAdjustable(
"string.allow.empty", Boolean.class, false);
/**
* Specifies whether generated Strings should be prefixed with field names;
* default is {@code false}; property name {@code string.field.prefix.enabled}.
*
* @since 2.4.0
*/
public static final SettingKey STRING_FIELD_PREFIX_ENABLED = registerRequiredNonAdjustable(
"string.field.prefix.enabled", Boolean.class, false);
/**
* Specifies minimum length of strings;
* default is 3; property name {@code string.min.length}.
*/
public static final SettingKey STRING_MIN_LENGTH = registerRequiredAdjustable(
"string.min.length", Integer.class, 3, MIN_ADJUSTER, false);
/**
* Specifies maximum length of strings;
* default is 10; property name {@code string.max.length}.
*/
public static final SettingKey STRING_MAX_LENGTH = registerRequiredAdjustable(
"string.max.length", Integer.class, 10, MAX_ADJUSTER, false);
/**
* Specifies whether a {@code null} can be generated for String type;
* default is {@code false}; property name {@code string.nullable}.
*/
public static final SettingKey STRING_NULLABLE = registerRequiredNonAdjustable(
"string.nullable", Boolean.class, false);
// Note: keys must be collected after all keys have been initialised
private static final Map> SETTING_KEY_MAP = Collections.unmodifiableMap(settingKeyMap());
private static Map> settingKeyMap() {
final Map> map = new HashMap<>();
for (SettingKey> key : ALL_KEYS) {
map.put(key.propertyKey(), key);
}
return map;
}
/**
* Returns all keys supported by Instancio.
*
* @return all keys
*/
public static List> all() {
return Collections.unmodifiableList(ALL_KEYS);
}
/**
* Returns a {@link SettingKey} instance with the given property key.
*
* @param key to lookup
* @return the setting key, or {@code null} if none found
*/
@SuppressWarnings("unchecked")
public static SettingKey get(@NotNull final String key) {
return (SettingKey) SETTING_KEY_MAP.get(key);
}
/**
* A builder for creating custom setting keys.
*
* When defining custom keys, specifying
* {@link SettingKeyBuilder#withPropertyKey(String)} is optional since
* not all settings will be defined in a properties file.
* If {@code withPropertyKey()} is not specified, then a random
* property key will be assigned.
*
* @param type of the value the key is associated with, not {@code null}
* @param the value type
* @return key builder
* @since 2.12.0
*/
@ExperimentalApi
public static SettingKeyBuilder ofType(final Class type) {
return InternalKey.builder(type);
}
private static SettingKey register(
@NotNull final String propertyKey,
@NotNull final Class type,
@Nullable final Object defaultValue,
@Nullable final RangeAdjuster rangeAdjuster,
final boolean allowsNullValue,
final boolean allowsNegative) {
final SettingKey settingKey = new InternalKey<>(
propertyKey, type, defaultValue, rangeAdjuster, allowsNullValue, allowsNegative);
ALL_KEYS.add((SettingKey