From 28415d456c558abc9f77ebf3d653d6ab4d2730ff Mon Sep 17 00:00:00 2001 From: jbisss Date: Thu, 30 Oct 2025 18:16:26 +0300 Subject: [PATCH] [hw_2] push --- .../java/org/example/GenerateExample.java | 58 ++++++++- .../org/example/classes/BinaryTreeNode.java | 12 ++ src/main/java/org/example/classes/Cart.java | 3 + .../java/org/example/classes/Example.java | 3 + .../java/org/example/classes/Product.java | 3 + .../java/org/example/classes/Rectangle.java | 3 + src/main/java/org/example/classes/Shape.java | 3 + .../java/org/example/classes/Triangle.java | 3 + .../example/generator/ComplexGenerator.java | 115 ++++++++++++++++++ .../org/example/generator/Generatable.java | 11 ++ .../java/org/example/generator/Generator.java | 5 +- .../org/example/generator/IGenerator.java | 8 ++ 12 files changed, 219 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/example/generator/ComplexGenerator.java create mode 100644 src/main/java/org/example/generator/Generatable.java create mode 100644 src/main/java/org/example/generator/IGenerator.java diff --git a/src/main/java/org/example/GenerateExample.java b/src/main/java/org/example/GenerateExample.java index 47679a9..cfdfc4d 100644 --- a/src/main/java/org/example/GenerateExample.java +++ b/src/main/java/org/example/GenerateExample.java @@ -1,15 +1,63 @@ package org.example; - -import org.example.classes.Example; +import org.example.classes.*; +import org.example.generator.ComplexGenerator; import org.example.generator.Generator; public class GenerateExample { + public static void main(String[] args) { - var gen = new Generator(); + generateByDefaultGenerator(); + generateByComplexGenerator(); + } + + private static void generateByDefaultGenerator() { + var defaultGenerator = new Generator(); + try { + System.out.println(defaultGenerator.generateValueOfType(Example.class)); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + private static void generateByComplexGenerator() { + var complexGenerator = new ComplexGenerator(); try { - Object generated = gen.generateValueOfType(Example.class); - System.out.println(generated); + System.out.println("------------------------------------"); + System.out.println("Example.class\n"); + Example exampleObj = (Example) complexGenerator.generateValueOfType(Example.class); + System.out.println(exampleObj); + System.out.println("------------------------------------"); + System.out.println("Product.class\n"); + Product product = (Product) complexGenerator.generateValueOfType(Product.class); + System.out.println(product.getName()); + System.out.println(product.getPrice()); + System.out.println("------------------------------------"); + System.out.println("Triangle.class\n"); + Triangle triangle = (Triangle) complexGenerator.generateValueOfType(Triangle.class); + System.out.println(triangle.getArea()); + System.out.println(triangle.getPerimeter()); + System.out.println("------------------------------------"); + System.out.println("Rectangle.class\n"); + Rectangle rectangle = (Rectangle) complexGenerator.generateValueOfType(Rectangle.class); + System.out.println(rectangle.getArea()); + System.out.println(rectangle.getPerimeter()); + System.out.println("------------------------------------"); + System.out.println("Cart.class\n"); + Cart cart = (Cart) complexGenerator.generateValueOfType(Cart.class); + System.out.println(cart.getItems()); + System.out.println("------------------------------------"); + System.out.println("BinaryTreeNode.class\n"); + BinaryTreeNode binaryTreeNode = (BinaryTreeNode) complexGenerator.generateValueOfType(BinaryTreeNode.class); + System.out.println(binaryTreeNode.getData()); + System.out.println(binaryTreeNode.getLeft()); + System.out.println(binaryTreeNode.getRight()); + System.out.println("------------------------------------"); + System.out.println("Shape.class\n"); + Shape shapeObj = (Shape) complexGenerator.generateValueOfType(Shape.class); + System.out.println(shapeObj.getPerimeter()); + System.out.println(shapeObj.getArea()); + System.out.println("------------------------------------"); } catch (Throwable e) { throw new RuntimeException(e); } diff --git a/src/main/java/org/example/classes/BinaryTreeNode.java b/src/main/java/org/example/classes/BinaryTreeNode.java index 046ff56..fcab56a 100644 --- a/src/main/java/org/example/classes/BinaryTreeNode.java +++ b/src/main/java/org/example/classes/BinaryTreeNode.java @@ -1,5 +1,8 @@ package org.example.classes; +import org.example.generator.Generatable; + +@Generatable public class BinaryTreeNode { private Integer data; private BinaryTreeNode left; @@ -30,4 +33,13 @@ public void setLeft(BinaryTreeNode left) { public void setRight(BinaryTreeNode right) { this.right = right; } + + @Override + public String toString() { + return "BinaryTreeNode{" + + "data=" + data + + ", left=" + left + + ", right=" + right + + "\n}"; + } } diff --git a/src/main/java/org/example/classes/Cart.java b/src/main/java/org/example/classes/Cart.java index 965237d..3b9e8dd 100644 --- a/src/main/java/org/example/classes/Cart.java +++ b/src/main/java/org/example/classes/Cart.java @@ -1,7 +1,10 @@ package org.example.classes; +import org.example.generator.Generatable; + import java.util.List; +@Generatable public class Cart { private List items; diff --git a/src/main/java/org/example/classes/Example.java b/src/main/java/org/example/classes/Example.java index eac9463..e0c8d1c 100644 --- a/src/main/java/org/example/classes/Example.java +++ b/src/main/java/org/example/classes/Example.java @@ -1,5 +1,8 @@ package org.example.classes; +import org.example.generator.Generatable; + +@Generatable public class Example { int i; diff --git a/src/main/java/org/example/classes/Product.java b/src/main/java/org/example/classes/Product.java index e7dcc89..ba7aa89 100644 --- a/src/main/java/org/example/classes/Product.java +++ b/src/main/java/org/example/classes/Product.java @@ -1,5 +1,8 @@ package org.example.classes; +import org.example.generator.Generatable; + +@Generatable public class Product { private String name; private double price; diff --git a/src/main/java/org/example/classes/Rectangle.java b/src/main/java/org/example/classes/Rectangle.java index 90b0886..5f6b174 100644 --- a/src/main/java/org/example/classes/Rectangle.java +++ b/src/main/java/org/example/classes/Rectangle.java @@ -1,5 +1,8 @@ package org.example.classes; +import org.example.generator.Generatable; + +@Generatable public class Rectangle implements Shape { private double length; private double width; diff --git a/src/main/java/org/example/classes/Shape.java b/src/main/java/org/example/classes/Shape.java index c20a851..7a6f41f 100644 --- a/src/main/java/org/example/classes/Shape.java +++ b/src/main/java/org/example/classes/Shape.java @@ -1,5 +1,8 @@ package org.example.classes; +import org.example.generator.Generatable; + +@Generatable public interface Shape { double getArea(); double getPerimeter(); diff --git a/src/main/java/org/example/classes/Triangle.java b/src/main/java/org/example/classes/Triangle.java index 011e96f..e2c4c5a 100644 --- a/src/main/java/org/example/classes/Triangle.java +++ b/src/main/java/org/example/classes/Triangle.java @@ -1,5 +1,8 @@ package org.example.classes; +import org.example.generator.Generatable; + +@Generatable public class Triangle implements Shape { private double sideA; private double sideB; diff --git a/src/main/java/org/example/generator/ComplexGenerator.java b/src/main/java/org/example/generator/ComplexGenerator.java new file mode 100644 index 0000000..0486bd6 --- /dev/null +++ b/src/main/java/org/example/generator/ComplexGenerator.java @@ -0,0 +1,115 @@ +package org.example.generator; + +import java.lang.reflect.*; +import java.util.*; +import java.util.stream.Collectors; + +public class ComplexGenerator implements IGenerator { + + private static final int NUMERIC_BOUND = 1000; + private static final int BYTE_BOUND = 256; + private static final int ALPHABET_BOUND = 26; + + private static final int RECURSION_BOUND = 5; + private static final int SEVERAL_VALUES_BOUND = 10; + + private class RandomInvocationHandler implements InvocationHandler { + + @Override + public Object invoke(Object proxy, Method method, Object[] args) { + Class returnType = method.getReturnType(); + return setRandomValueForParameter(returnType, returnType, 0); + } + } + + @Override + public Object generateValueOfType(Class clazz) { + if (!isGeneratable(clazz)) return null; + if (clazz.isInterface()) return handleInterface(clazz); + return handleClass(clazz, 0); + } + + private boolean isGeneratable(Class clazz) { + return !Arrays.stream(clazz.getAnnotations()) + .filter(it -> it instanceof Generatable) + .collect(Collectors.toSet()).isEmpty(); + } + + private Object handleInterface(Class iClass) { + return Proxy.newProxyInstance( + iClass.getClassLoader(), + new Class[]{iClass}, + new RandomInvocationHandler() + ); + } + + private Object handleClass(Class clazz, int recursionLevel) { + if (recursionLevel > RECURSION_BOUND) return null; + Constructor[] constructors = clazz.getDeclaredConstructors(); + + int randomConstructorIndex = new Random().nextInt(constructors.length); + Constructor randomConstructor = constructors[randomConstructorIndex]; + return defineParameterTypeAndCreateObject(randomConstructor, recursionLevel); + } + + private Object defineParameterTypeAndCreateObject(Constructor constructor, int recursionLevel) { + Class[] parameterTypes = constructor.getParameterTypes(); + Type[] genericParameterTypes = constructor.getGenericParameterTypes(); + + Object[] parametersValues = new Object[parameterTypes.length]; + for (int i = 0; i < parametersValues.length; i++) { + parametersValues[i] = setRandomValueForParameter(parameterTypes[i], genericParameterTypes[i], recursionLevel); + } + Object newInstance; + try { + newInstance = constructor.newInstance(parametersValues); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + return newInstance; + } + + private Object setRandomValueForParameter(Class parameterType, Type genericType, int recursionLevel) { + Random random = new Random(); + if (parameterType == boolean.class || parameterType == Boolean.class) return random.nextBoolean(); + if (parameterType == byte.class || parameterType == Byte.class) return random.nextInt(BYTE_BOUND); + if (parameterType == int.class || parameterType == Integer.class) return random.nextInt(NUMERIC_BOUND); + if (parameterType == long.class || parameterType == Long.class) return random.nextLong(NUMERIC_BOUND); + if (parameterType == double.class || parameterType == Double.class) return random.nextDouble(NUMERIC_BOUND); + if (parameterType == float.class || parameterType == Float.class) return random.nextFloat(NUMERIC_BOUND); + if (parameterType == char.class || parameterType == Character.class) return 'a' + random.nextInt(ALPHABET_BOUND); + if (parameterType == String.class) return generateRandomString(); + + int severalValuesLength = new Random().nextInt(SEVERAL_VALUES_BOUND); + if (parameterType.isArray()) { + Class componentType = parameterType.getComponentType(); + Object array = Array.newInstance(componentType, severalValuesLength); + for (int i = 0; i < severalValuesLength; i++) { + Array.set(array, i, handleClass(componentType, recursionLevel)); + } + return array; + } + + if (Collection.class.isAssignableFrom(parameterType)) { + List list = new ArrayList<>(); + if (genericType instanceof ParameterizedType parameterizedType) { + Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0]; + Class elementClass = (Class) actualTypeArgument; + for (int i = 0; i < severalValuesLength; i++) { + list.add(handleClass(elementClass, recursionLevel)); + } + } + return list; + } + + return handleClass(parameterType, recursionLevel + 1); + } + + private Object generateRandomString() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < 26; i++) { + stringBuilder.append(Character.toChars('A' + new Random().nextInt(26))[0]); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/org/example/generator/Generatable.java b/src/main/java/org/example/generator/Generatable.java new file mode 100644 index 0000000..4cd7adc --- /dev/null +++ b/src/main/java/org/example/generator/Generatable.java @@ -0,0 +1,11 @@ +package org.example.generator; + +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.TYPE) +public @interface Generatable { +} diff --git a/src/main/java/org/example/generator/Generator.java b/src/main/java/org/example/generator/Generator.java index 9d86bfb..98283e3 100644 --- a/src/main/java/org/example/generator/Generator.java +++ b/src/main/java/org/example/generator/Generator.java @@ -4,8 +4,9 @@ import java.lang.reflect.InvocationTargetException; import java.util.Random; -public class Generator { +public class Generator implements IGenerator { + @Override public Object generateValueOfType(Class clazz) throws InvocationTargetException, InstantiationException, IllegalAccessException { Constructor[] constructors = clazz.getDeclaredConstructors(); @@ -13,6 +14,4 @@ public Object generateValueOfType(Class clazz) throws InvocationTargetExcepti Constructor randomConstructor = constructors[randomConstructorIndex]; return randomConstructor.newInstance(111); } - - } diff --git a/src/main/java/org/example/generator/IGenerator.java b/src/main/java/org/example/generator/IGenerator.java new file mode 100644 index 0000000..4b7f9c0 --- /dev/null +++ b/src/main/java/org/example/generator/IGenerator.java @@ -0,0 +1,8 @@ +package org.example.generator; + +import java.lang.reflect.InvocationTargetException; + +public interface IGenerator { + + public Object generateValueOfType(Class clazz) throws InvocationTargetException, InstantiationException, IllegalAccessException; +}