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

Домашняя работа №10 #14

Merged
merged 6 commits into from
Jan 4, 2024
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
8 changes: 8 additions & 0 deletions src/main/java/edu/hw10/task1/FieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package edu.hw10.task1;

import java.lang.annotation.Annotation;
import java.util.Random;

public interface FieldGenerator<T> {
T generate(Random random, Annotation[] annotations);
}
83 changes: 83 additions & 0 deletions src/main/java/edu/hw10/task1/RandomObjectGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package edu.hw10.task1;

import edu.hw10.task1.annotations.NotNull;
import edu.hw10.task1.generators.Generators;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public final class RandomObjectGenerator {

private final Random random;
private final Mode mode;
private final Map<Class<?>, FieldGenerator<?>> generators;

public RandomObjectGenerator(Random random, Mode mode) {
this.random = random;
this.generators = new HashMap<>(Generators.defaultGenerators());
this.mode = mode;
}

public <T> T nextObject(Class<T> clazz) {
Constructor<?> constructor = ReflectionUtils.getConstructorWithMaxParams(clazz);
return nextObject(clazz, constructor);
}

public <T> T nextObjectWithSpecifiedConstructor(Class<T> clazz, Class<?>... params) {
try {
Constructor<?> constructor = clazz.getConstructor(params);
return nextObject(clazz, constructor);
} catch (Exception e) {
throw new IllegalArgumentException(
"Failed to create an instance of with specified constructor " + clazz.getName(), e);
}
}

public <T> T nextObject(Class<T> clazz, Constructor<?> constructor) {
Object[] params = generateParams(constructor.getParameters());
try {
return clazz.cast(constructor.newInstance(params));
} catch (Exception e) {
throw new IllegalStateException("Failed to create an instance of " + clazz.getName(), e);
}
}

public <T> T nextObject(Class<T> clazz, String factoryMethod) {
Method method = ReflectionUtils.getMethod(clazz, factoryMethod);
Object[] params = generateParams(method.getParameters());
try {
return clazz.cast(method.invoke(null, params));
} catch (Exception e) {
throw new IllegalStateException(
"Failed to create an instance with method " + factoryMethod + " of " + clazz.getName(), e);
}
}

private Object[] generateParams(Parameter[] parameters) {
Object[] params = new Object[parameters.length];
for (int i = 0; i < params.length; i++) {
FieldGenerator<?> generator = generators.get(parameters[i].getType());
if (generator == null) {
if (mode == Mode.GENERATE_NESTED
|| (mode == Mode.SKIP_NESTED_IF_CAN && parameters[i].isAnnotationPresent(NotNull.class))) {
params[i] = nextObject(parameters[i].getType());
}
} else {
params[i] = generator.generate(random, parameters[i].getAnnotations());
}
}
return params;
}

public enum Mode {
SKIP_NESTED_ALWAYS,
SKIP_NESTED_IF_CAN,
GENERATE_NESTED
}

}
35 changes: 35 additions & 0 deletions src/main/java/edu/hw10/task1/ReflectionUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package edu.hw10.task1;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public final class ReflectionUtils {

private ReflectionUtils() {
}

public static Constructor<?> getConstructorWithMaxParams(Class<?> clazz) {
Constructor<?>[] constructors = clazz.getConstructors();
if (constructors.length == 0) {
throw new IllegalArgumentException("Class " + clazz.getName() + " has no constructors");
}
Constructor<?> constructor = constructors[0];
int paramCount = constructor.getParameterCount();
for (Constructor<?> value : constructors) {
if (value.getParameterCount() > paramCount) {
constructor = value;
paramCount = constructor.getParameterCount();
}
}
return constructor;
}

public static Method getMethod(Class<?> clazz, String methodName) {
for (Method method : clazz.getMethods()) {
if (method.getName().equals(methodName)) {
return method;
}
}
throw new IllegalArgumentException("No method " + methodName + " in " + clazz.getName());
}
}
12 changes: 12 additions & 0 deletions src/main/java/edu/hw10/task1/annotations/Max.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package edu.hw10.task1.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Max {
long value();
}
12 changes: 12 additions & 0 deletions src/main/java/edu/hw10/task1/annotations/Min.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package edu.hw10.task1.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Min {
long value();
}
11 changes: 11 additions & 0 deletions src/main/java/edu/hw10/task1/annotations/NotNull.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package edu.hw10.task1.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface NotNull {
}
12 changes: 12 additions & 0 deletions src/main/java/edu/hw10/task1/generators/BooleanFieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import java.lang.annotation.Annotation;
import java.util.Random;

public class BooleanFieldGenerator implements FieldGenerator<Boolean> {
@Override
public Boolean generate(Random random, Annotation[] annotations) {
return random.nextBoolean();
}
}
25 changes: 25 additions & 0 deletions src/main/java/edu/hw10/task1/generators/ByteFieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import edu.hw10.task1.annotations.Max;
import edu.hw10.task1.annotations.Min;
import java.lang.annotation.Annotation;
import java.util.Random;

public class ByteFieldGenerator implements FieldGenerator<Byte> {

@Override
public Byte generate(Random random, Annotation[] annotations) {
int min = Byte.MIN_VALUE;
int max = Byte.MAX_VALUE - 1;
for (Annotation annotation : annotations) {
if (annotation instanceof Min minAnnotation) {
min = (int) minAnnotation.value();
}
if (annotation instanceof Max maxAnnotation) {
max = (int) maxAnnotation.value();
}
}
return (byte) random.nextInt(min, max + 1);
}
}
24 changes: 24 additions & 0 deletions src/main/java/edu/hw10/task1/generators/DoubleFieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import edu.hw10.task1.annotations.Max;
import edu.hw10.task1.annotations.Min;
import java.lang.annotation.Annotation;
import java.util.Random;

public class DoubleFieldGenerator implements FieldGenerator<Double> {
@Override
public Double generate(Random random, Annotation[] annotations) {
double min = Double.MIN_VALUE;
double max = Double.MAX_VALUE - 1;
for (Annotation annotation : annotations) {
if (annotation instanceof Min minAnnotation) {
min = minAnnotation.value();
}
if (annotation instanceof Max maxAnnotation) {
max = maxAnnotation.value();
}
}
return random.nextDouble(min, max + 1);
}
}
24 changes: 24 additions & 0 deletions src/main/java/edu/hw10/task1/generators/FloatFieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import edu.hw10.task1.annotations.Max;
import edu.hw10.task1.annotations.Min;
import java.lang.annotation.Annotation;
import java.util.Random;

public class FloatFieldGenerator implements FieldGenerator<Float> {
@Override
public Float generate(Random random, Annotation[] annotations) {
float min = Float.MIN_VALUE;
float max = Float.MAX_VALUE - 1;
for (Annotation annotation : annotations) {
if (annotation instanceof Min minAnnotation) {
min = minAnnotation.value();
}
if (annotation instanceof Max maxAnnotation) {
max = maxAnnotation.value();
}
}
return random.nextFloat(min, max + 1);
}
}
31 changes: 31 additions & 0 deletions src/main/java/edu/hw10/task1/generators/Generators.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import java.util.HashMap;
import java.util.Map;

public final class Generators {

private Generators() {
}

public static Map<Class<?>, FieldGenerator<?>> defaultGenerators() {
HashMap<Class<?>, FieldGenerator<?>> generators = new HashMap<>();

generators.put(String.class, new StringFieldGenerator());
generators.put(byte.class, new ByteFieldGenerator());
generators.put(int.class, new IntFieldGenerator());
generators.put(long.class, new LongFieldGenerator());
generators.put(float.class, new FloatFieldGenerator());
generators.put(double.class, new DoubleFieldGenerator());
generators.put(boolean.class, new BooleanFieldGenerator());
generators.put(Byte.class, new ByteFieldGenerator());
generators.put(Integer.class, new IntFieldGenerator());
generators.put(Long.class, new LongFieldGenerator());
generators.put(Float.class, new FloatFieldGenerator());
generators.put(Double.class, new DoubleFieldGenerator());
generators.put(Boolean.class, new BooleanFieldGenerator());

return generators;
}
}
24 changes: 24 additions & 0 deletions src/main/java/edu/hw10/task1/generators/IntFieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import edu.hw10.task1.annotations.Max;
import edu.hw10.task1.annotations.Min;
import java.lang.annotation.Annotation;
import java.util.Random;

public class IntFieldGenerator implements FieldGenerator<Integer> {
@Override
public Integer generate(Random random, Annotation[] annotations) {
int min = Integer.MIN_VALUE;
int max = Integer.MAX_VALUE - 1;
for (Annotation annotation : annotations) {
if (annotation instanceof Min minAnnotation) {
min = (int) minAnnotation.value();
}
if (annotation instanceof Max maxAnnotation) {
max = (int) maxAnnotation.value();
}
}
return random.nextInt(min, max + 1);
}
}
25 changes: 25 additions & 0 deletions src/main/java/edu/hw10/task1/generators/LongFieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import edu.hw10.task1.annotations.Max;
import edu.hw10.task1.annotations.Min;
import java.lang.annotation.Annotation;
import java.util.Random;

public class LongFieldGenerator implements FieldGenerator<Long> {
@Override
public Long generate(Random random, Annotation[] annotations) {
long min = Long.MIN_VALUE;
long max = Long.MAX_VALUE - 1;
for (Annotation annotation : annotations) {
if (annotation instanceof Min minAnnotation) {
min = minAnnotation.value();
}
if (annotation instanceof Max maxAnnotation) {
max = maxAnnotation.value();
}
}
return random.nextLong(min, max + 1);
}

}
36 changes: 36 additions & 0 deletions src/main/java/edu/hw10/task1/generators/StringFieldGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package edu.hw10.task1.generators;

import edu.hw10.task1.FieldGenerator;
import edu.hw10.task1.annotations.Max;
import edu.hw10.task1.annotations.Min;
import java.lang.annotation.Annotation;
import java.util.Random;

public class StringFieldGenerator implements FieldGenerator<String> {

private static final char[] ALPHABET =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
private static final int DEFAULT_MIN_LENGTH = 10;
private static final int DEFAULT_MAX_LENGTH = 100;

@Override
public String generate(Random random, Annotation[] annotations) {
int minLength = DEFAULT_MIN_LENGTH;
int maxLength = DEFAULT_MAX_LENGTH;

for (Annotation annotation : annotations) {
if (annotation instanceof Min minAnnotation) {
minLength = (int) minAnnotation.value();
}
if (annotation instanceof Max maxAnnotation) {
maxLength = (int) maxAnnotation.value();
}
}
int length = random.nextInt(minLength, maxLength + 1);
StringBuilder randomStringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
randomStringBuilder.append(ALPHABET[random.nextInt(0, ALPHABET.length)]);
}
return randomStringBuilder.toString();
}
}
11 changes: 11 additions & 0 deletions src/main/java/edu/hw10/task2/Cache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package edu.hw10.task2;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(java.lang.annotation.ElementType.METHOD)
public @interface Cache {
boolean persist() default false;
}
Loading