Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure compatibility with Android's limited Java SE subset #48

Merged
merged 2 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion easy-random-bean-validation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-bean-validation</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion easy-random-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ public <T> T createInstance(Class<T> type, RandomizerContext context) {
private <T> T createNewInstance(final Class<T> type) {
try {
Constructor<T> noArgConstructor = type.getDeclaredConstructor();
noArgConstructor.trySetAccessible();
try {
noArgConstructor.trySetAccessible();
} catch(NoSuchMethodError e) {
noArgConstructor.setAccessible(true);
}
return noArgConstructor.newInstance();
} catch (Exception exception) {
return objenesis.newInstance(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@
*/
package org.jeasy.random.randomizers.registry;

import static java.sql.Date.valueOf;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
Expand Down Expand Up @@ -132,4 +131,8 @@ public Randomizer<?> getRandomizer(final Field field) {
public Randomizer<?> getRandomizer(Class<?> type) {
return randomizers.get(type);
}

private static Date valueOf(LocalDate date) {
return new Date(date.getYear() - 1900, date.getMonthValue() -1, date.getDayOfMonth());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.concurrent.*;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.jeasy.random.ObjectCreationException;
import org.jeasy.random.annotation.RandomizerArgument;
import org.jeasy.random.api.Randomizer;
Expand All @@ -42,20 +43,22 @@
/**
* Reflection utility methods.
*
* <strong>This class is intended for internal use only. All public methods
* (except {@link ReflectionUtils#asRandomizer(java.util.function.Supplier)}
* might change between minor versions without notice.</strong>
* <strong>This class is intended for internal use only. All public methods
* (except {@link ReflectionUtils#asRandomizer(java.util.function.Supplier)}
* might change between minor versions without notice.</strong>
*
* @author Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
*/
public final class ReflectionUtils {

private ReflectionUtils() {}
private ReflectionUtils() {
}

/**
* Create a dynamic proxy that adapts the given {@link Supplier} to a {@link Randomizer}.
*
* @param supplier to adapt
* @param <T> target type
* @param <T> target type
* @return the proxy randomizer
*/
@SuppressWarnings("unchecked")
Expand All @@ -80,9 +83,9 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg
}

return (Randomizer<T>) Proxy.newProxyInstance(
Randomizer.class.getClassLoader(),
new Class[] { Randomizer.class },
new RandomizerProxy(supplier)
Randomizer.class.getClassLoader(),
new Class[]{Randomizer.class},
new RandomizerProxy(supplier)
);
}

Expand Down Expand Up @@ -124,7 +127,7 @@ public static List<Field> getInheritedFields(Class<?> type) {
* @throws IllegalAccessException if the property cannot be set
*/
public static void setProperty(final Object object, final Field field, final Object value)
throws IllegalAccessException, InvocationTargetException {
throws IllegalAccessException, InvocationTargetException {
try {
Optional<Method> setter = getWriteMethod(field);
if (setter.isPresent()) {
Expand All @@ -147,10 +150,15 @@ public static void setProperty(final Object object, final Field field, final Obj
* @throws IllegalAccessException if the property cannot be set
*/
public static void setFieldValue(final Object object, final Field field, final Object value)
throws IllegalAccessException {
boolean access = field.trySetAccessible();
field.set(object, value);
field.setAccessible(access);
throws IllegalAccessException {
try {
boolean access = field.trySetAccessible();
field.set(object, value);
field.setAccessible(access);
} catch (NoSuchMethodError e) {
field.setAccessible(true);
field.set(object, value);
}
}

/**
Expand All @@ -162,10 +170,15 @@ public static void setFieldValue(final Object object, final Field field, final O
* @throws IllegalAccessException if field cannot be accessed
*/
public static Object getFieldValue(final Object object, final Field field) throws IllegalAccessException {
boolean access = field.trySetAccessible();
Object value = field.get(object);
field.setAccessible(access);
return value;
try {
boolean access = field.trySetAccessible();
Object value = field.get(object);
field.setAccessible(access);
return value;
} catch (NoSuchMethodError e) {
field.setAccessible(true);
return field.get(object);
}
}

/**
Expand Down Expand Up @@ -193,7 +206,7 @@ public static Class<?> getWrapperType(Class<?> primitiveType) {
* @throws IllegalAccessException if field cannot be accessed
*/
public static boolean isPrimitiveFieldWithDefaultValue(final Object object, final Field field)
throws IllegalAccessException {
throws IllegalAccessException {
Class<?> fieldType = field.getType();
if (!fieldType.isPrimitive()) {
return false;
Expand Down Expand Up @@ -329,10 +342,10 @@ public static boolean isPopulatable(final Type type) {
*/
public static boolean isIntrospectable(final Class<?> type) {
return (
!isEnumType(type) &&
!isArrayType(type) &&
!(isCollectionType(type) && isJdkBuiltIn(type)) &&
!(isMapType(type) && isJdkBuiltIn(type))
!isEnumType(type) &&
!isArrayType(type) &&
!(isCollectionType(type) && isJdkBuiltIn(type)) &&
!(isMapType(type) && isJdkBuiltIn(type))
);
}

Expand Down Expand Up @@ -421,11 +434,11 @@ public static List<Class<?>> filterSameParameterizedTypes(final List<Class<?>> t
for (Class<?> currentConcreteType : types) {
List<Type[]> actualTypeArguments = getActualTypeArgumentsOfGenericInterfaces(currentConcreteType);
typesWithSameParameterizedTypes.addAll(
actualTypeArguments
.stream()
.filter(currentTypeArguments -> Arrays.equals(fieldArugmentTypes, currentTypeArguments))
.map(currentTypeArguments -> currentConcreteType)
.toList()
actualTypeArguments
.stream()
.filter(currentTypeArguments -> Arrays.equals(fieldArugmentTypes, currentTypeArguments))
.map(currentTypeArguments -> currentConcreteType)
.toList()
);
}
return typesWithSameParameterizedTypes;
Expand All @@ -436,29 +449,29 @@ public static List<Class<?>> filterSameParameterizedTypes(final List<Class<?>> t
/**
* Looks for given annotationType on given field or read method for field.
*
* @param field field to check
* @param field field to check
* @param annotationType Type of annotation you're looking for.
* @param <T> the actual type of annotation
* @param <T> the actual type of annotation
* @return given annotation if field or read method has this annotation or null.
*/
public static <T extends Annotation> T getAnnotation(Field field, Class<T> annotationType) {
return field.getAnnotation(annotationType) == null
? getAnnotationFromReadMethod(getReadMethod(field).orElse(null), annotationType)
: field.getAnnotation(annotationType);
? getAnnotationFromReadMethod(getReadMethod(field).orElse(null), annotationType)
: field.getAnnotation(annotationType);
}

/**
* Checks if field or corresponding read method is annotated with given annotationType.
*
* @param field Field to check
* @param field Field to check
* @param annotationType Annotation you're looking for.
* @return true if field or read method it annotated with given annotationType or false.
*/
public static boolean isAnnotationPresent(Field field, Class<? extends Annotation> annotationType) {
final Optional<Method> readMethod = getReadMethod(field);
return (
field.isAnnotationPresent(annotationType) ||
(readMethod.isPresent() && readMethod.get().isAnnotationPresent(annotationType))
field.isAnnotationPresent(annotationType) ||
(readMethod.isPresent() && readMethod.get().isAnnotationPresent(annotationType))
);
}

Expand Down Expand Up @@ -494,7 +507,8 @@ public static Collection<?> getEmptyImplementationForCollectionInterface(final C

/**
* Create an empty collection for the given type.
* @param fieldType for which an empty collection should we created
*
* @param fieldType for which an empty collection should we created
* @param initialSize initial size of the collection
* @return empty collection
*/
Expand All @@ -504,7 +518,7 @@ public static Collection<?> createEmptyCollectionForType(Class<?> fieldType, int
try {
collection = (Collection<?>) fieldType.getDeclaredConstructor().newInstance();
} catch (
InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e
InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e
) {
if (fieldType.equals(ArrayBlockingQueue.class)) {
collection = new ArrayBlockingQueue<>(initialSize);
Expand All @@ -517,6 +531,7 @@ public static Collection<?> createEmptyCollectionForType(Class<?> fieldType, int

/**
* Return an empty implementation for the given {@link Map} interface.
*
* @param mapInterface for which an empty implementation should be returned
* @return empty implementation for the given {@link Map} interface.
*/
Expand Down Expand Up @@ -557,6 +572,7 @@ public static Optional<Method> getWriteMethod(Field field) {

/**
* Get the read method for given field.
*
* @param field field to get the read method for.
* @return Optional of read method or empty if field has no read method
*/
Expand Down Expand Up @@ -605,27 +621,27 @@ public static <T> Randomizer<T> newInstance(final Class<T> type, final Randomize
try {
if (notEmpty(randomizerArguments)) {
Optional<Constructor<?>> matchingConstructor = Stream
.of(type.getConstructors())
.filter(constructor ->
hasSameArgumentNumber(constructor, randomizerArguments) &&
hasSameArgumentTypes(constructor, randomizerArguments)
)
.findFirst();
.of(type.getConstructors())
.filter(constructor ->
hasSameArgumentNumber(constructor, randomizerArguments) &&
hasSameArgumentTypes(constructor, randomizerArguments)
)
.findFirst();
if (matchingConstructor.isPresent()) {
return (Randomizer<T>) matchingConstructor.get().newInstance(convertArguments(randomizerArguments));
}
}
return (Randomizer<T>) type.getDeclaredConstructor().newInstance();
} catch (
IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e
IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e
) {
throw new ObjectCreationException(
format(
"Could not create Randomizer of type: %s with constructor arguments: %s",
type,
Arrays.toString(randomizerArguments)
),
e
format(
"Could not create Randomizer of type: %s with constructor arguments: %s",
type,
Arrays.toString(randomizerArguments)
),
e
);
}
}
Expand All @@ -635,15 +651,15 @@ private static boolean notEmpty(final RandomizerArgument[] randomizerArguments)
}

private static boolean hasSameArgumentNumber(
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
) {
return constructor.getParameterCount() == randomizerArguments.length;
}

private static boolean hasSameArgumentTypes(
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
final Constructor<?> constructor,
final RandomizerArgument[] randomizerArguments
) {
Class<?>[] constructorParameterTypes = constructor.getParameterTypes();
for (int i = 0; i < randomizerArguments.length; i++) {
Expand Down
2 changes: 1 addition & 1 deletion easy-random-protobuf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-protobuf</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion easy-random-randomizers/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random-randomizers</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.dvgaba</groupId>
<artifactId>easy-random</artifactId>
<version>7.1.0</version>
<version>7.1.1-SNAPSHOT</version>
<packaging>pom</packaging>

<build>
Expand Down
Loading