diff --git a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java index e2cdac5..a2cfbe5 100644 --- a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java +++ b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java @@ -1,6 +1,5 @@ package com.bobocode.net.client; -import com.bobocode.util.ExerciseNotCompletedException; import lombok.SneakyThrows; import java.io.*; @@ -24,7 +23,7 @@ private ClientUtil() { */ @SneakyThrows public static Socket openSocket(String host, int port) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ClientUtilTest + return new Socket(host, port); } /** @@ -62,6 +61,9 @@ public static String readMessage(BufferedReader reader) { */ @SneakyThrows public static void writeToSocket(String message, Socket socket) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ClientUtilTest + OutputStream outputStream = socket.getOutputStream(); + Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream)); + writer.write(message); + writer.flush(); } } diff --git a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java index 3778579..1797c5a 100644 --- a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java +++ b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java @@ -1,6 +1,5 @@ package com.bobocode.net.server; -import com.bobocode.util.ExerciseNotCompletedException; import lombok.SneakyThrows; import java.io.BufferedReader; @@ -41,7 +40,7 @@ public static String getLocalHost() { */ @SneakyThrows public static ServerSocket createServerSocket(int port) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ServerUtilTest + return new ServerSocket(port); } /** @@ -52,7 +51,7 @@ public static ServerSocket createServerSocket(int port) { */ @SneakyThrows public static Socket acceptClientSocket(ServerSocket serverSocket) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ServerUtilTest + return serverSocket.accept(); } /** @@ -66,7 +65,9 @@ public static Socket acceptClientSocket(ServerSocket serverSocket) { */ @SneakyThrows public static String readMessageFromSocket(Socket socket) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ServerUtilTest + InputStream inputStream = socket.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + return reader.readLine(); } /** diff --git a/2-0-servlet-api/2-0-1-hello-servlet-api/src/main/java/com/bobocode/servlet/DateServlet.java b/2-0-servlet-api/2-0-1-hello-servlet-api/src/main/java/com/bobocode/servlet/DateServlet.java new file mode 100644 index 0000000..413f25d --- /dev/null +++ b/2-0-servlet-api/2-0-1-hello-servlet-api/src/main/java/com/bobocode/servlet/DateServlet.java @@ -0,0 +1,21 @@ +package com.bobocode.servlet; + +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.io.PrintWriter; +import java.time.LocalDate; + +@WebServlet("/date") +public class DateServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + PrintWriter out = response.getWriter(); + LocalDate date = LocalDate.now(); + out.println(date); + } +} diff --git a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java index f7ebf38..ed14d85 100644 --- a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java +++ b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java @@ -1,6 +1,7 @@ package com.bobocode.config; import com.bobocode.TestDataGenerator; +import org.springframework.context.annotation.*; /** * This class specifies application context configuration. It tells Spring to scan "dao" and "service" packages in order @@ -10,7 +11,13 @@ * It also explicitly configures a bean of {@link TestDataGenerator} called "dataGenerator". This beans will be injected * into {@link com.bobocode.dao.FakeAccountDao} in order to generate some fake accounts. */ + +@Configuration +@ComponentScan(basePackages = {"com.bobocode.dao", "com.bobocode.service"}) public class ApplicationConfig { - // todo: configure application context according to javadoc by following tests in ApplicationConfigTest - // todo: verify final implementation by running ApplicationContextTest + + @Bean + public TestDataGenerator dataGenerator() { + return new TestDataGenerator(); + } } diff --git a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java index bae7264..988a90b 100644 --- a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java +++ b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java @@ -2,6 +2,8 @@ import com.bobocode.TestDataGenerator; import com.bobocode.model.Account; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Stream; @@ -16,9 +18,11 @@ * Its bean is called "accountDao". And it uses constructor with explicit autowired annotation in order to inject * {@link TestDataGenerator} instance. */ +@Component("accountDao") public class FakeAccountDao implements AccountDao { private List<Account> accounts; + @Autowired public FakeAccountDao(TestDataGenerator testDataGenerator) { this.accounts = Stream.generate(testDataGenerator::generateAccount) .limit(20) diff --git a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java index a46dfd2..d6d69b8 100644 --- a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java +++ b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java @@ -2,6 +2,7 @@ import com.bobocode.dao.AccountDao; import com.bobocode.model.Account; +import org.springframework.stereotype.Service; import static java.util.Comparator.comparing; @@ -12,6 +13,7 @@ * Since it's a service that should be added to the application context, it is marked as Spring service. It order to get * {@link AccountDao} instances, it uses implicit constructor-based injection. */ +@Service public class AccountService { private final AccountDao accountDao; diff --git a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java index 95d9ed6..61d4385 100644 --- a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java +++ b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java @@ -1,7 +1,11 @@ package com.bobocode.mvc.api; import com.bobocode.mvc.data.Notes; +import com.bobocode.mvc.model.Note; import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; /** * This controller provides a very simple REST API for Notes. It implements two endpoints that allow you to add @@ -18,9 +22,20 @@ * Spring MVC was used to build the whole application including front-end. So the controllers were connected to the views * via models, like in {@link com.bobocode.mvc.controller.NoteController} */ +@RestController +@RequestMapping("/api/notes") @RequiredArgsConstructor public class NoteRestController { + private final Notes notes; - // TODO: implement controller methods according to the javadoc verify your impl using NoteRestControllerTest -} + @GetMapping + public List<Note> getNotes() { + return notes.getAll(); + } + + @PostMapping + public void addNote(@RequestBody Note note) { + notes.add(note); + } +} \ No newline at end of file diff --git a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java index 3f9d528..485c6da 100644 --- a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java +++ b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java @@ -1,7 +1,13 @@ package com.bobocode.mvc.controller; import com.bobocode.mvc.data.Notes; +import com.bobocode.mvc.model.Note; import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; /** * {@link NoteController} is a typical controller that powers Spring MVC Notes application. This application provides @@ -26,10 +32,21 @@ * back-end applications. The back-end app, will only need to provide data and don't care about view. In that case * the same controller will look like {@link com.bobocode.mvc.api.NoteRestController} */ +@Controller +@RequestMapping("/notes") @RequiredArgsConstructor public class NoteController { private final Notes notes; - // TODO: implement controller methods according to the javadoc and verify your impl using NoteControllerTest + @GetMapping + public String getNotes(Model model) { + model.addAttribute("noteList", notes.getAll()); + return "notes"; + } -} + @PostMapping + public String addNote(Note note) { + notes.add(note); + return "redirect:/notes"; + } +} \ No newline at end of file diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java index 6536634..2c55fbf 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java @@ -15,5 +15,8 @@ * todo: enable component scanning for all packages in "com.bobocode" * todo: ignore all web related config and beans (ignore @{@link Controller}, ignore {@link EnableWebMvc}) using exclude filter */ +@Configuration +@ComponentScan(basePackages = "com.bobocode", excludeFilters = + {@Filter(Controller.class), @Filter(EnableWebMvc.class)}) public class RootConfig { } diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java index ee23400..e5e154f 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java @@ -9,16 +9,16 @@ public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { - throw new ExerciseNotCompletedException(); //todo: use {@link RootConfig} as root application config class + return new Class[]{RootConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { - throw new ExerciseNotCompletedException(); //todo: use {@link WebConfig} as ServletConfig class + return new Class[]{WebConfig.class}; } @Override protected String[] getServletMappings() { - throw new ExerciseNotCompletedException(); //todo: provide default servlet mapping ("/") + return new String[]{"/"}; } } diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java index 66d3a84..dea1246 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java @@ -13,6 +13,8 @@ * todo: enable web mvc using annotation * todo: enable component scanning for package "web" */ - +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "com.bobocode.web") public class WebConfig { } diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java index 77392cc..12dc892 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java @@ -1,5 +1,9 @@ package com.bobocode.web.controller; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + /** * Welcome controller that consists of one method that handles get request to "/welcome" and respond with a message. * <p> @@ -8,8 +12,11 @@ * todo: tell Spring that {@link WelcomeController#welcome()} method provides response body without view */ +@Controller public class WelcomeController { + @GetMapping("/welcome") + @ResponseBody public String welcome() { return "Welcome to Spring MVC!"; } diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java index c5d1a6d..84d2933 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java @@ -1,5 +1,7 @@ package com.bobocode.config; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -10,5 +12,7 @@ * todo: 2. Enable component scanning for all packages in "com.bobocode" using annotation property "basePackages" * todo: 3. Exclude web related config and beans (ignore @{@link Controller}, ignore {@link EnableWebMvc}) */ +@Configuration +@ComponentScan(basePackages = "com.bobocode", excludeFilters = {@ComponentScan.Filter(EnableWebMvc.class), @ComponentScan.Filter(Controller.class)}) public class RootConfig { } diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java index 1197302..8aa34fa 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java @@ -1,5 +1,9 @@ package com.bobocode.config; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + /** * This class provides web (servlet) related configuration. * <p> @@ -7,5 +11,9 @@ * todo: 2. Enable web mvc using annotation * todo: 3. Enable component scanning for package "web" using annotation value */ +@EnableWebMvc +@Configuration +@ComponentScan(basePackages = "com.bobocode.web") public class WebConfig { + } diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java index 5620d5b..c43089e 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java @@ -3,6 +3,7 @@ import com.bobocode.dao.AccountDao; import com.bobocode.exception.EntityNotFountException; import com.bobocode.model.Account; +import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.HashMap; @@ -14,6 +15,7 @@ * <p> * todo: 1. Configure a component with name "accountDao" */ +@Component("accountDao") public class InMemoryAccountDao implements AccountDao { private Map<Long, Account> accountMap = new HashMap<>(); private long idSequence = 1L; diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java index 84fb818..afcc2fc 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java @@ -1,6 +1,12 @@ package com.bobocode.web.controller; import com.bobocode.dao.AccountDao; +import com.bobocode.model.Account; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Objects; /** * <p> @@ -16,6 +22,44 @@ * todo: 7. Implement method that handles DELETE request with id as path variable removes an account by id * todo: Configure HTTP response status code 204 - NO CONTENT */ +@RestController +@RequestMapping("/accounts") public class AccountRestController { + private final AccountDao accountDao; + + public AccountRestController(AccountDao accountDao) { + this.accountDao = accountDao; + } + + @GetMapping + public List<Account> getAll() { + return accountDao.findAll(); + } + + @GetMapping("/{id}") + public Account getOne(@PathVariable long id) { + return accountDao.findById(id); + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public Account create(@RequestBody Account account) { + return accountDao.save(account); + } + + @PutMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void update(@PathVariable long id, @RequestBody Account account) { + if (!Objects.equals(id, account.getId())) { + throw new IllegalStateException("Id parameter does not match account body value"); + } + accountDao.save(account); + } + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void remove(@PathVariable long id) { + Account account = accountDao.findById(id); + accountDao.remove(account); + } } diff --git a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/StringTrimmingConfiguration.java b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/StringTrimmingConfiguration.java new file mode 100644 index 0000000..1e14972 --- /dev/null +++ b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/StringTrimmingConfiguration.java @@ -0,0 +1,19 @@ +package com.bobocode; + +import com.bobocode.annotation.EnableStringTrimming; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Class to provide a bean of {@link TrimmedAnnotationBeanPostProcessor}. + * </p> + * Note! This class is not a {@link Configuration} class itself, but can be imported to a config class by the + * {@link EnableStringTrimming} annotation + */ +public class StringTrimmingConfiguration { + + @Bean + public TrimmedAnnotationBeanPostProcessor trimmedAnnotationBeanPostProcessor() { + return new TrimmedAnnotationBeanPostProcessor(); + } +} diff --git a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java index ee1d441..4e1c57a 100644 --- a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java +++ b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java @@ -1,9 +1,19 @@ package com.bobocode; import com.bobocode.annotation.Trimmed; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; /** * This is processor class implements {@link BeanPostProcessor}, looks for a beans where method parameters are marked with @@ -16,6 +26,54 @@ * {@link StringTrimmingConfiguration} class which can be imported to a {@link Configuration} class by annotation * {@link EnableStringTrimming} */ -public class TrimmedAnnotationBeanPostProcessor { -//todo: Implement TrimmedAnnotationBeanPostProcessor according to javadoc +public class TrimmedAnnotationBeanPostProcessor implements BeanPostProcessor { + + private final Map<String, Class<?>> beansToBeProxied = new HashMap<>(); + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (containsParametersAnnotatedWithTrimmed(bean)) { + beansToBeProxied.put(beanName, bean.getClass()); + } + return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + Class<?> toProxy = beansToBeProxied.get(beanName); + if (toProxy != null) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(toProxy); + enhancer.setCallback(provideTrimmingInterceptor()); + return enhancer.create(); + } + return bean; + } + + private MethodInterceptor provideTrimmingInterceptor() { + return (beanInstance, method, args, methodProxy) -> + methodProxy.invokeSuper(beanInstance, processParameters(method, args)); + } + + private Object[] processParameters(Method method, Object[] args) { + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + if (parameters[i].isAnnotationPresent(Trimmed.class)) { + args[i] = trimMarkedString(args[i]); + } + } + return args; + } + + private Object trimMarkedString(Object arg) { + if (arg instanceof String string) { + return StringUtils.hasLength(string) ? string.trim() : arg; + } + return arg; + } + + private boolean containsParametersAnnotatedWithTrimmed(Object bean) { + return Arrays.stream(bean.getClass().getDeclaredMethods()).flatMap(m -> Stream.of(m.getParameters())) + .anyMatch(p -> p.isAnnotationPresent(Trimmed.class)); + } } diff --git a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java index 8c06d65..e40525a 100644 --- a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java +++ b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java @@ -1,8 +1,17 @@ package com.bobocode.annotation; +import com.bobocode.StringTrimmingConfiguration; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.context.annotation.Import; + /** * Annotation that can be placed on configuration class to import {@link StringTrimmingConfiguration} */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Import(StringTrimmingConfiguration.class) public @interface EnableStringTrimming { -//todo: Implement EnableStringTrimming annotation according to javadoc }