Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package ru.otus.appcontainer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import ru.otus.appcontainer.api.AppComponent;
import ru.otus.appcontainer.api.AppComponentsContainer;
import ru.otus.appcontainer.api.AppComponentsContainerConfig;
import ru.otus.appcontainer.exception.AppComponentContainerException;

@SuppressWarnings("squid:S1068")
public class AppComponentsContainerImpl implements AppComponentsContainer {
Expand All @@ -19,7 +20,24 @@ public AppComponentsContainerImpl(Class<?> initialConfigClass) {

private void processConfig(Class<?> configClass) {
checkConfigClass(configClass);
// You code here...
var config = getConfigObject(configClass);
var componentsInitMethods = Arrays.stream(configClass.getMethods())
.filter(method -> method.isAnnotationPresent(AppComponent.class))
.sorted(Comparator.comparingInt(
method -> method.getAnnotation(AppComponent.class).order()))
.toList();
for (Method componentInitMethod : componentsInitMethods) {
var componentName =
componentInitMethod.getAnnotation(AppComponent.class).name();
if (!appComponentsByName.containsKey(componentName)) {
var component = initComponent(componentInitMethod, config);
appComponents.add(component);
appComponentsByName.put(componentName, component);
} else {
throw new AppComponentContainerException(
String.format("Component with name %s already exist", componentName));
}
}
}

private void checkConfigClass(Class<?> configClass) {
Expand All @@ -28,13 +46,46 @@ private void checkConfigClass(Class<?> configClass) {
}
}

private Object getConfigObject(Class<?> configClass) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лучше назвать createConfigObject

try {
return configClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new AppComponentContainerException(
String.format("Config %s cannot be create", configClass.getName()), e);
}
}

private Object initComponent(Method componentInitMethod, Object config) {
var parameters = Arrays.stream(componentInitMethod.getParameterTypes())
.map(this::getAppComponent)
.toArray();
try {
return componentInitMethod.invoke(config, parameters);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new AppComponentContainerException(
String.format("Method %s cannot be invoke", componentInitMethod.getName()), e);
}
}

@Override
public <C> C getAppComponent(Class<C> componentClass) {
return null;
var components =
appComponents.stream().filter(componentClass::isInstance).toList();
if (components.isEmpty()) {
throw new AppComponentContainerException(String.format("Component %s not found", componentClass.getName()));
} else if (components.size() > 1) {
throw new AppComponentContainerException(
String.format("More than one component %s found", componentClass.getName()));
}
return (C) components.get(0);
}

@Override
public <C> C getAppComponent(String componentName) {
return null;
if (appComponentsByName.containsKey(componentName)) {
return (C) appComponentsByName.get(componentName);
} else {
throw new AppComponentContainerException(String.format("Component %s not found", componentName));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ru.otus.appcontainer.exception;

public class AppComponentContainerException extends RuntimeException {
public AppComponentContainerException(String message) {
super(message);
}

public AppComponentContainerException(String message, Exception cause) {
super(message, cause);
}
}
4 changes: 0 additions & 4 deletions hw13-di/src/test/java/ru/otus/AppTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.util.Arrays;
import java.util.Scanner;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand All @@ -21,7 +20,6 @@

class AppTest {

@Disabled("Эту аннотацию надо убрать")
@DisplayName("Из контекста тремя способами должен корректно доставаться компонент с проставленными полями")
@ParameterizedTest(name = "Достаем по: {0}")
@CsvSource(
Expand Down Expand Up @@ -74,15 +72,13 @@ void shouldExtractFromContextCorrectComponentWithNotNullFields(String classNameO
}
}

@Disabled("Эту аннотацию надо убрать")
@DisplayName("В контексте не должно быть компонентов с одинаковым именем")
@Test
void shouldNotAllowTwoComponentsWithSameName() {
assertThatCode(() -> new AppComponentsContainerImpl(ConfigWithTwoComponentsWithSameName.class))
.isInstanceOf(Exception.class);
}

@Disabled("Эту аннотацию надо убрать")
@DisplayName(
"При попытке достать из контекста отсутствующий или дублирующийся компонент, должно выкидываться исключение")
@Test
Expand Down