-
Notifications
You must be signed in to change notification settings - Fork 34
Reflect hw2 #5
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
base: master
Are you sure you want to change the base?
Reflect hw2 #5
Changes from all commits
fc57525
d52b243
f97fd21
1e865bd
99940a2
901bcf2
0faf9ba
7a1863d
a522968
4c09579
6574c7c
56927be
ccf67ac
9759ab9
96fa855
75c7c46
8c75d19
2ac97b9
ef3cd83
192cbaa
bec05e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package org.example.annotation; | ||
|
|
||
| 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 { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,22 @@ | ||
| package org.example.classes; | ||
|
|
||
| import org.example.annotation.Generatable; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @Generatable | ||
| public class Cart { | ||
| private List<Product> items; | ||
| private List<org.example.classes.Product> items; | ||
|
|
||
| public Cart(List<Product> items) { | ||
| public Cart(List<org.example.classes.Product> items) { | ||
| this.items = items; | ||
| } | ||
|
|
||
| public List<Product> getItems() { | ||
| public List<org.example.classes.Product> getItems() { | ||
| return items; | ||
| } | ||
|
|
||
| public void setItems(List<Product> items) { | ||
| public void setItems(List<org.example.classes.Product> items) { | ||
| this.items = items; | ||
| } | ||
|
|
||
| // Конструктор, методы добавления и удаления товаров, геттеры и другие методы | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package main.java.org.example.generator; | ||
|
|
||
| import java.io.Serializable; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import java.util.Random; | ||
| import java.util.concurrent.atomic.AtomicBoolean; | ||
| import java.util.concurrent.atomic.AtomicInteger; | ||
| import java.util.concurrent.atomic.AtomicLong; | ||
| import java.util.concurrent.atomic.AtomicReference; | ||
| import java.util.function.Supplier; | ||
|
|
||
| public class AtomicGenerator { | ||
| private final Random random = new Random(); | ||
| private final Map<Class<?>, Supplier<Object>> generators; | ||
|
|
||
| public AtomicGenerator() | ||
| { | ||
| generators = new HashMap<>(); | ||
| generators.put(AtomicInteger.class, () -> new AtomicInteger(random.nextInt(Integer.MAX_VALUE))); | ||
| generators.put(AtomicLong.class, () -> new AtomicLong(random.nextInt(Integer.MAX_VALUE))); | ||
| generators.put(AtomicBoolean.class, () -> new AtomicBoolean(random.nextBoolean())); | ||
| generators.put(AtomicReference.class, () -> new AtomicReference<>(random.nextInt())); | ||
| } | ||
|
|
||
| public Object generate(Class<?> clazz) | ||
| { | ||
| Supplier<Object> supplier = generators.get(clazz); | ||
| if (supplier == null) { | ||
| return null; | ||
| } | ||
| return supplier.get(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package org.example.generator; | ||
|
|
||
| import net.bytebuddy.ByteBuddy; | ||
|
|
||
| import java.lang.reflect.InvocationTargetException; | ||
|
|
||
| public class FromInterfaceGenerator { | ||
|
|
||
| public Object generate(Class<?> clazz) throws | ||
| ClassNotFoundException, | ||
| InvocationTargetException, | ||
| IllegalAccessException, | ||
| NoSuchMethodException, | ||
| InstantiationException | ||
| { | ||
| String className = clazz.getName(); | ||
| Class<?> interfaceClass = Class.forName(className); | ||
| Class<?> dynamicType = new ByteBuddy() | ||
| .subclass(Object.class) | ||
| .implement(interfaceClass) | ||
| .make() | ||
| .load(clazz.getClassLoader()) | ||
| .getLoaded(); | ||
| Object instance = dynamicType.getDeclaredConstructor().newInstance(); | ||
| boolean implementsInterface = clazz.isAssignableFrom(instance.getClass()); | ||
| System.out.println("Implements interface? " + implementsInterface); | ||
| return instance; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,105 @@ | ||
| package org.example.generator; | ||
|
|
||
| import java.lang.reflect.Constructor; | ||
| import java.lang.reflect.InvocationTargetException; | ||
| import java.util.Random; | ||
| import main.java.org.example.generator.*; | ||
| import org.example.annotation.Generatable; | ||
|
|
||
| import java.lang.reflect.*; | ||
| import java.util.*; | ||
| import java.util.concurrent.*; | ||
|
|
||
|
|
||
| public class Generator { | ||
|
|
||
| public Object generateValueOfType(Class<?> clazz) throws InvocationTargetException, InstantiationException, IllegalAccessException { | ||
| Constructor<?>[] constructors = clazz.getDeclaredConstructors(); | ||
| private final Random random = new Random(); | ||
| private final PrimitiveGenerator primitiveGenerator = new PrimitiveGenerator(); | ||
| private final AtomicGenerator atomicGenerator = new AtomicGenerator(); | ||
| private final QueueGenerator queueGenerator = new QueueGenerator(); | ||
| private final SequenceGenerator sequenceGenerator = new SequenceGenerator(); | ||
| private final MapGenerator mapGenerator = new MapGenerator(); | ||
| private final FromInterfaceGenerator fromInterfaceGenerator = new FromInterfaceGenerator(); | ||
| private static final int MAX_DEPTH = 10; | ||
|
|
||
| public Object generateValueOfType(Type type, int depth) throws | ||
| InvocationTargetException, | ||
| InstantiationException, | ||
| IllegalAccessException, | ||
| NoSuchMethodException, | ||
| ClassNotFoundException | ||
| { | ||
| if (depth > MAX_DEPTH) { | ||
| return null; | ||
| } | ||
| if (type instanceof Class<?> clazz) { | ||
| Object primitiveValue = primitiveGenerator.generate(clazz); | ||
| if (primitiveValue != null) return primitiveValue; | ||
|
|
||
| Object atomicValue = atomicGenerator.generate(clazz); | ||
| if (atomicValue != null) return atomicValue; | ||
|
|
||
| Object queueValue = queueGenerator.generate(clazz); | ||
| if (queueValue != null) return queueValue; | ||
|
|
||
| int randomConstructorIndex = new Random().nextInt(constructors.length); | ||
| Constructor<?> randomConstructor = constructors[randomConstructorIndex]; | ||
| return randomConstructor.newInstance(111); | ||
| if (Collection.class.isAssignableFrom(clazz)) { | ||
| return sequenceGenerator.generate(clazz); | ||
| } | ||
| if (Map.class.isAssignableFrom(clazz)) { | ||
| return mapGenerator.generate(clazz); | ||
| } | ||
| if (clazz.isEnum()) { | ||
| Object[] arr = clazz.getEnumConstants(); | ||
| return arr[random.nextInt(arr.length)]; | ||
| } | ||
| if (clazz.isInterface()) { | ||
| return fromInterfaceGenerator.generate(clazz); | ||
| } | ||
| return generateType(clazz, depth + 1); | ||
| } | ||
|
|
||
| if (type instanceof ParameterizedType pType) { | ||
| Type raw = pType.getRawType(); | ||
| if (!(raw instanceof Class<?> rawClass)) { | ||
| throw new IllegalArgumentException("Unsupported raw type: " + raw); | ||
| } | ||
| if (Collection.class.isAssignableFrom(rawClass)) { | ||
| Collection<Object> collection; | ||
| if (rawClass.isInterface()) { | ||
| collection = new ArrayList<>(); | ||
| } else { | ||
| collection = (Collection<Object>) rawClass.getDeclaredConstructor().newInstance(); | ||
| } | ||
| Type elementType = pType.getActualTypeArguments()[0]; | ||
| for (int i = 0; i < 3; i++) { | ||
| Object element = generateValueOfType(elementType, depth + 1); | ||
| collection.add(element); | ||
| } | ||
| return collection; | ||
| } | ||
| return generateType((Class<?>) rawClass, depth + 1); | ||
| } | ||
| throw new IllegalArgumentException("Unsupported type: " + type); | ||
| } | ||
|
|
||
| private Object generateType(Class<?> clazz, int depth) throws | ||
| InvocationTargetException, | ||
| InstantiationException, | ||
| IllegalAccessException, | ||
| NoSuchMethodException, | ||
| ClassNotFoundException | ||
| { | ||
| Constructor<?> constructor = clazz.getDeclaredConstructors()[0]; | ||
|
|
||
| if (!clazz.isAnnotationPresent(Generatable.class)) { | ||
| throw new IllegalArgumentException("Class " + clazz.getName() + " has no Generatable annotation"); | ||
| } | ||
|
|
||
| Type[] paramTypes = constructor.getGenericParameterTypes(); | ||
| Object[] params = new Object[paramTypes.length]; | ||
|
|
||
| for (int i = 0; i < paramTypes.length; i++) { | ||
| params[i] = generateValueOfType(paramTypes[i], depth + 1); | ||
| } | ||
|
|
||
| constructor.setAccessible(true); | ||
| return constructor.newInstance(params); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package main.java.org.example.generator; | ||
|
|
||
| import java.util.*; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.function.Supplier; | ||
|
|
||
| public class MapGenerator { | ||
| private final Random random = new Random(); | ||
| private final Map<Class<?>, Supplier<Object>> generators = new HashMap<>(); | ||
|
|
||
| public MapGenerator() | ||
| { | ||
| generators.put(HashMap.class, () -> { | ||
| HashMap<String, Object> map = new HashMap<>(); | ||
| fillMap(map); | ||
| return map; | ||
| }); | ||
| generators.put(LinkedHashMap.class, () -> { | ||
| LinkedHashMap<String , Object> map = new LinkedHashMap<>(); | ||
| fillMap(map); | ||
| return map; | ||
| }); | ||
| generators.put(TreeMap.class, () -> { | ||
| TreeMap<String, Object> map = new TreeMap<>(); | ||
| fillMap(map); | ||
| return map; | ||
| }); | ||
| generators.put(ConcurrentHashMap.class, () -> { | ||
| ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>(); | ||
| fillMap(map); | ||
| return map; | ||
| }); | ||
| generators.put(WeakHashMap.class, () -> { | ||
| WeakHashMap<String, Object> map = new WeakHashMap<>(); | ||
| fillMap(map); | ||
| return map; | ||
| }); | ||
| generators.put(IdentityHashMap.class, () -> { | ||
| IdentityHashMap<String, Object> map = new IdentityHashMap<>(); | ||
| fillMap(map); | ||
| return map; | ||
| }); | ||
| } | ||
|
|
||
| private void fillMap(Map<String, Object> map) | ||
| { | ||
| int randomSize = random.nextInt(100); | ||
| for (int i = 0; i < randomSize; i++) { | ||
| map.put(String.valueOf(i), new Object()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. На самом деле таки есть способ получить типы из коллекций вроде есть. Просьба потом отписать, как оно устроено и почемы мы можем получить типы несмотря на стирание
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да, это можно сделать, проблема в том что type erasure работает на уровне рантайма, но данные остаются в метаданных обьявления переменной. Но такое не будет работать для обьектов которые созданы прям совсем на лету Я исправил код и попробовал сгенерировать класс с джеенрик типом, результат: Все получилось |
||
| } | ||
| } | ||
|
|
||
| public Map<String, Object> generate(Class<?> clazz) | ||
| { | ||
| Supplier<Object> supplier = generators.get(clazz); | ||
| if (supplier == null) { | ||
| return null; | ||
| } | ||
| return (Map<String, Object>) supplier.get(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
У нас в целом задача -- создание разнообразных объектов случайных. Как на счет идеи пройтись по полям и случайно их сгенерировать?