-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Solution #1254
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: main
Are you sure you want to change the base?
Solution #1254
Changes from 1 commit
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 |
|---|---|---|
|
|
@@ -8,9 +8,8 @@ | |
| public class Main { | ||
|
|
||
| public static void main(String[] args) { | ||
|
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. Similarly to |
||
| // Please test your Injector here. Feel free to push this class as a part of your solution | ||
| Injector injector = Injector.getInjector(); | ||
| ProductService productService = null; | ||
| ProductService productService = (ProductService) injector.getInstance(ProductService.class); | ||
| List<Product> products = productService.getAllFromFile("products.txt"); | ||
| products.forEach(System.out::println); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,11 @@ | ||
| package mate.academy.lib; | ||
|
|
||
| public @interface Component { | ||
| 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 Component { | ||
|
Comment on lines
+8
to
+10
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. The annotations are correctly configured with
Comment on lines
+8
to
+10
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. The annotations are correctly configured with |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,11 @@ | ||
| package mate.academy.lib; | ||
|
|
||
| public @interface Inject { | ||
| 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.FIELD) | ||
|
Comment on lines
+8
to
+9
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. The annotation is correctly marked with |
||
| public @interface Inject { | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package mate.academy.lib; | ||
|
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.
|
||
|
|
||
| public class InjectionException extends RuntimeException { | ||
| public InjectionException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public InjectionException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,108 @@ | ||
| package mate.academy.lib; | ||
|
|
||
| import java.io.File; | ||
| import java.io.IOException; | ||
| import java.lang.reflect.Constructor; | ||
| import java.lang.reflect.Field; | ||
| import java.net.URL; | ||
| import java.util.ArrayList; | ||
| import java.util.Enumeration; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| public class Injector { | ||
| private static final Injector injector = new Injector(); | ||
| private final Map<Class<?>, Object> instances = new HashMap<>(); | ||
| private final Map<Class<?>, Class<?>> interfaceImplementations = new HashMap<>(); | ||
|
Comment on lines
+5
to
+17
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. The annotation usage here ( |
||
|
|
||
| private Injector() { | ||
| try { | ||
| List<Class<?>> classes = getClasses("mate.academy"); | ||
| for (Class<?> clazz : classes) { | ||
| if (clazz.isAnnotationPresent(Component.class)) { | ||
| Class<?>[] interfaces = clazz.getInterfaces(); | ||
| if (interfaces.length > 0) { | ||
| interfaceImplementations.put(interfaces[0], clazz); | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+17
to
+29
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. Populating |
||
| } catch (Exception e) { | ||
| throw new RuntimeException("Can't initialize injector", e); | ||
|
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. Catching a broad |
||
| } | ||
| } | ||
|
|
||
| public static Injector getInjector() { | ||
| return injector; | ||
| } | ||
|
|
||
| public Object getInstance(Class<?> interfaceClazz) { | ||
| return null; | ||
| if (instances.containsKey(interfaceClazz)) { | ||
| return instances.get(interfaceClazz); | ||
|
Comment on lines
+16
to
+41
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. Using the |
||
| } | ||
| Class<?> clazz = findImplementation(interfaceClazz); | ||
| if (clazz == null || !clazz.isAnnotationPresent(Component.class)) { | ||
| throw new InjectionException("Missing @Component annotation on class " | ||
| + "or no implementation for " + interfaceClazz.getName()); | ||
| } | ||
| try { | ||
| Constructor<?> constructor = clazz.getConstructor(); | ||
| Object instance = constructor.newInstance(); | ||
| Field[] fields = clazz.getDeclaredFields(); | ||
| for (Field field : fields) { | ||
| if (field.isAnnotationPresent(Inject.class)) { | ||
| Object fieldInstance = getInstance(field.getType()); | ||
| field.setAccessible(true); | ||
| field.set(instance, fieldInstance); | ||
| } | ||
| } | ||
| instances.put(interfaceClazz, instance); | ||
| return instance; | ||
| } catch (ReflectiveOperationException e) { | ||
|
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. Catching |
||
| throw new InjectionException("Can't create instance of " + clazz.getName(), e); | ||
| } | ||
| } | ||
|
|
||
| private Class<?> findImplementation(Class<?> interfaceClazz) { | ||
| if (interfaceClazz.isInterface()) { | ||
| return interfaceImplementations.get(interfaceClazz); | ||
| } | ||
| return interfaceClazz; | ||
| } | ||
|
|
||
| private static List<Class<?>> getClasses(String packageName) | ||
| throws ClassNotFoundException, IOException { | ||
| ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | ||
| String path = packageName.replace('.', '/'); | ||
| Enumeration<URL> resources = classLoader.getResources(path); | ||
| List<File> dirs = new ArrayList<>(); | ||
| while (resources.hasMoreElements()) { | ||
| URL resource = resources.nextElement(); | ||
| dirs.add(new File(resource.getFile())); | ||
| } | ||
| ArrayList<Class<?>> classes = new ArrayList<>(); | ||
| for (File directory : dirs) { | ||
| classes.addAll(findClasses(directory, packageName)); | ||
| } | ||
| return classes; | ||
| } | ||
|
|
||
| private static List<Class<?>> findClasses(File directory, String packageName) | ||
| throws ClassNotFoundException { | ||
| List<Class<?>> classes = new ArrayList<>(); | ||
| if (!directory.exists()) { | ||
| return classes; | ||
| } | ||
| File[] files = directory.listFiles(); | ||
| for (File file : files) { | ||
| if (file.isDirectory()) { | ||
| classes.addAll(findClasses(file, packageName + "." + file.getName())); | ||
| } else if (file.getName().endsWith(".class")) { | ||
| String className = packageName + '.' | ||
| + file.getName().substring(0, file.getName().length() - 6); | ||
| classes.add(Class.forName(className)); | ||
| } | ||
| } | ||
| return classes; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,11 @@ | ||
| package mate.academy.service.impl; | ||
|
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.
|
||
|
|
||
| import java.math.BigDecimal; | ||
| import mate.academy.lib.Component; | ||
|
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. This class also imports |
||
| import mate.academy.model.Product; | ||
| import mate.academy.service.ProductParser; | ||
|
|
||
|
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. This class relies on |
||
| @Component | ||
| public class ProductParserImpl implements ProductParser { | ||
| public static final int ID_POSITION = 0; | ||
| public static final int NAME_POSITION = 1; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,13 +2,18 @@ | |
|
|
||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
| import mate.academy.lib.Component; | ||
| import mate.academy.lib.Inject; | ||
| import mate.academy.model.Product; | ||
| import mate.academy.service.FileReaderService; | ||
|
Comment on lines
3
to
8
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.
|
||
| import mate.academy.service.ProductParser; | ||
| import mate.academy.service.ProductService; | ||
|
|
||
| @Component | ||
|
Comment on lines
+5
to
+12
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.
|
||
| public class ProductServiceImpl implements ProductService { | ||
| @Inject | ||
| private ProductParser productParser; | ||
| @Inject | ||
| private FileReaderService fileReaderService; | ||
|
|
||
| @Override | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
||
|
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. This file is completely empty; per the task description, 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. This file is completely empty; per the task description, 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. This file is completely empty; the assignment requires a custom 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. This file is completely empty; the assignment’s core requirement is an |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
||
|
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. This file is empty, but the project already has a fully implemented 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. This file is an empty duplicate of the 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.
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. The |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
||
|
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. 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. This file is empty, but the project imports 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.
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. The core |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
||
|
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. This file is empty but is supposed to define the 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. This file is empty but should define the 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.
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. The |
||
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.
The custom
@Componentannotation needs to live in the same package that the rest of the codebase imports (mate.academy.lib); make sure you are not accidentally maintaining duplicateComponentdefinitions in different packages, as this can cause runtime confusion and violate the requirement to use only one@Componentannotation (checklist item #2).