From c40d6962dd5c630b7079297e7ba8ae90a55073e6 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Sat, 4 Feb 2017 13:45:39 +0000 Subject: [PATCH 01/12] Added ConcurrentModificationException test --- .../ConcurrentModificationUnitTest.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java new file mode 100644 index 0000000000..9db460abbd --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.java.concurrentmodificationexception; + +import org.assertj.core.api.Assertions; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.Iterator; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.util.Lists.newArrayList; + +public class ConcurrentModificationUnitTest { + @Test(expected = ConcurrentModificationException.class) + public void whilstRemovingDuringIteration_shouldThrowException() throws InterruptedException { + + ArrayList integers = newArrayList(1, 2, 3); + + for (Integer integer : integers) { + integers.remove(1); + } + } + + @Test + public void whilstRemovingDuringIteration_shouldNotThrowException() throws InterruptedException { + + ArrayList integers = newArrayList(1, 2, 3); + + for (Iterator iterator = integers.iterator(); iterator.hasNext();) { + Integer integer = iterator.next(); + if(integer == 2) { + iterator.remove(); + } + } + + assertThat(integers).containsExactly(1, 3); + } + + @Test + public void whilstRemovingDuringForEach_shouldNotThrowException() throws InterruptedException { + + ArrayList integers = newArrayList(1, 2, 3); + ArrayList toRemove = newArrayList(); + + for (Integer integer : integers) { + if(integer == 2) { + toRemove.add(integer); + } + } + integers.removeAll(toRemove); + + assertThat(integers).containsExactly(1, 3); + } +} From 0a444d32cf1d9bb9225a0e28d54e2576fe718775 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Mon, 6 Feb 2017 21:55:24 +0000 Subject: [PATCH 02/12] Renamed unit tests for ConcurrentModificationUnit --- .../ConcurrentModificationUnitTest.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java index 9db460abbd..11c6012ecd 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.util.Lists.newArrayList; public class ConcurrentModificationUnitTest { @Test(expected = ConcurrentModificationException.class) - public void whilstRemovingDuringIteration_shouldThrowException() throws InterruptedException { + public void givenIterating_whenRemoving_thenThrowException() throws InterruptedException { ArrayList integers = newArrayList(1, 2, 3); @@ -22,7 +22,7 @@ public class ConcurrentModificationUnitTest { } @Test - public void whilstRemovingDuringIteration_shouldNotThrowException() throws InterruptedException { + public void givenIterating_whenUsingIteratorRemove_thenDontError() throws InterruptedException { ArrayList integers = newArrayList(1, 2, 3); @@ -37,7 +37,7 @@ public class ConcurrentModificationUnitTest { } @Test - public void whilstRemovingDuringForEach_shouldNotThrowException() throws InterruptedException { + public void givenIterating_whenUsingRemovalList_thenDontError() throws InterruptedException { ArrayList integers = newArrayList(1, 2, 3); ArrayList toRemove = newArrayList(); @@ -51,4 +51,14 @@ public class ConcurrentModificationUnitTest { assertThat(integers).containsExactly(1, 3); } + + @Test + public void whenUsingRemoveIf_thenRemoveElements() throws InterruptedException { + + ArrayList integers = newArrayList(1, 2, 3); + + integers.removeIf((i) -> i == 2); + + assertThat(integers).containsExactly(1, 3); + } } From 24760595fac8755287f7f540e7a118294cadfb3d Mon Sep 17 00:00:00 2001 From: lor6 Date: Tue, 7 Feb 2017 06:13:18 +0200 Subject: [PATCH 03/12] 2 login pages config (#1081) * 2 login pages config * fix links * small fix * fix formatting --- spring-mvc-forms/pom.xml | 18 +++ .../configuration/SecurityConfig.java | 122 ++++++++++++++++++ .../configuration/WebInitializer.java | 4 + .../controller/UsersController.java | 38 ++++++ .../src/main/webapp/WEB-INF/views/403.jsp | 12 ++ .../main/webapp/WEB-INF/views/adminPage.jsp | 16 +++ .../main/webapp/WEB-INF/views/loginAdmin.jsp | 38 ++++++ .../main/webapp/WEB-INF/views/loginUser.jsp | 37 ++++++ .../webapp/WEB-INF/views/protectedLinks.jsp | 16 +++ .../main/webapp/WEB-INF/views/userPage.jsp | 15 +++ 10 files changed, 316 insertions(+) create mode 100644 spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/SecurityConfig.java create mode 100644 spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UsersController.java create mode 100644 spring-mvc-forms/src/main/webapp/WEB-INF/views/403.jsp create mode 100644 spring-mvc-forms/src/main/webapp/WEB-INF/views/adminPage.jsp create mode 100644 spring-mvc-forms/src/main/webapp/WEB-INF/views/loginAdmin.jsp create mode 100644 spring-mvc-forms/src/main/webapp/WEB-INF/views/loginUser.jsp create mode 100644 spring-mvc-forms/src/main/webapp/WEB-INF/views/protectedLinks.jsp create mode 100644 spring-mvc-forms/src/main/webapp/WEB-INF/views/userPage.jsp diff --git a/spring-mvc-forms/pom.xml b/spring-mvc-forms/pom.xml index 31a0c38791..f17d695c35 100644 --- a/spring-mvc-forms/pom.xml +++ b/spring-mvc-forms/pom.xml @@ -46,6 +46,23 @@ commons-fileupload ${fileupload.version} + + + org.springframework.security + spring-security-web + ${org.springframework.security.version} + + + org.springframework.security + spring-security-config + ${org.springframework.security.version} + + + org.springframework.security + spring-security-taglibs + ${org.springframework.security.version} + + @@ -98,6 +115,7 @@ 5.3.3.Final enter-location-of-server 1.3.2 + 4.2.1.RELEASE diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/SecurityConfig.java b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/SecurityConfig.java new file mode 100644 index 0000000000..e35844138d --- /dev/null +++ b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/SecurityConfig.java @@ -0,0 +1,122 @@ +package com.baeldung.springmvcforms.configuration; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.TestingAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public UserDetailsService userDetailsService() throws Exception { + InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); + manager.createUser(User.withUsername("user") + .password("userPass") + .roles("USER") + .build()); + manager.createUser(User.withUsername("admin") + .password("adminPass") + .roles("ADMIN") + .build()); + return manager; + } + + @Configuration + @Order(1) + public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter { + + public App1ConfigurationAdapter() { + super(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin") + .password("admin") + .roles("ADMIN"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/admin*") + .authorizeRequests() + .anyRequest() + .hasRole("ADMIN") + // log in + .and() + .formLogin() + .loginPage("/loginAdmin") + .loginProcessingUrl("/admin_login") + .failureUrl("/loginAdmin?error=loginError") + .defaultSuccessUrl("/adminPage") + // logout + .and() + .logout() + .logoutUrl("/admin_logout") + .logoutSuccessUrl("/protectedLinks") + .deleteCookies("JSESSIONID") + .and() + .exceptionHandling() + .accessDeniedPage("/403") + .and() + .csrf() + .disable(); + } + } + + @Configuration + @Order(2) + public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter { + + public App2ConfigurationAdapter() { + super(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("user") + .password("user") + .roles("USER"); + } + + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/user*") + .authorizeRequests() + .anyRequest() + .hasRole("USER") + // log in + .and() + .formLogin() + .loginPage("/loginUser") + .loginProcessingUrl("/user_login") + .failureUrl("/loginUser?error=loginError") + .defaultSuccessUrl("/userPage") + // logout + .and() + .logout() + .logoutUrl("/user_logout") + .logoutSuccessUrl("/protectedLinks") + .deleteCookies("JSESSIONID") + .and() + .exceptionHandling() + .accessDeniedPage("/403") + .and() + .csrf() + .disable(); + } + } + +} diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java index c602ea6454..fdc155e101 100644 --- a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java +++ b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java @@ -3,6 +3,7 @@ package com.baeldung.springmvcforms.configuration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.filter.DelegatingFilterProxy; import org.springframework.web.servlet.DispatcherServlet; import javax.servlet.ServletContext; @@ -24,6 +25,9 @@ public class WebInitializer implements WebApplicationInitializer { servlet.setLoadOnStartup(1); servlet.addMapping("/"); + + container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain")) + .addMappingForUrlPatterns(null, false, "/*"); } // @Override // public void onStartup(ServletContext container) { diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UsersController.java b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UsersController.java new file mode 100644 index 0000000000..c0858d427f --- /dev/null +++ b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UsersController.java @@ -0,0 +1,38 @@ +package com.baeldung.springmvcforms.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class UsersController { + + @RequestMapping("/protectedLinks") + public String getAnonymousPage() { + return "protectedLinks"; + } + + @RequestMapping("/userPage") + public String getUserPage() { + return "userPage"; + } + + @RequestMapping("/adminPage") + public String getAdminPage() { + return "adminPage"; + } + + @RequestMapping("/loginAdmin") + public String getAdminLoginPage() { + return "loginAdmin"; + } + + @RequestMapping("/loginUser") + public String getUserLoginPage() { + return "loginUser"; + } + + @RequestMapping("/403") + public String getAccessDeniedPage() { + return "403"; + } +} diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/403.jsp b/spring-mvc-forms/src/main/webapp/WEB-INF/views/403.jsp new file mode 100644 index 0000000000..e665793e10 --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/WEB-INF/views/403.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + + + + +Your do not have permission to view this page. + + \ No newline at end of file diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/adminPage.jsp b/spring-mvc-forms/src/main/webapp/WEB-INF/views/adminPage.jsp new file mode 100644 index 0000000000..a210b690b0 --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/WEB-INF/views/adminPage.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + +Insert title here + + +Welcome admin! Logout + +

+Back to links + + \ No newline at end of file diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/loginAdmin.jsp b/spring-mvc-forms/src/main/webapp/WEB-INF/views/loginAdmin.jsp new file mode 100644 index 0000000000..a6b2ee7914 --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/WEB-INF/views/loginAdmin.jsp @@ -0,0 +1,38 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + + + + +Insert title here + + + +

Admin login page

+
+ + + + + + + + + + + + + +
User:
Password:
+ +
+ + <% + if (request.getParameter("error") != null) { + out.println("Login failed!"); + } + %> + + + \ No newline at end of file diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/loginUser.jsp b/spring-mvc-forms/src/main/webapp/WEB-INF/views/loginUser.jsp new file mode 100644 index 0000000000..e65c11edaf --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/WEB-INF/views/loginUser.jsp @@ -0,0 +1,37 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + + + + +Login + + + +

User login page

+ +
+ + + + + + + + + + + + +
User:
Password:
+ +
+ <% + if (request.getParameter("error") != null) { + out.println("Login failed!"); + } + %> + + + \ No newline at end of file diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/protectedLinks.jsp b/spring-mvc-forms/src/main/webapp/WEB-INF/views/protectedLinks.jsp new file mode 100644 index 0000000000..b8453903ba --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/WEB-INF/views/protectedLinks.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + +Insert title here + + + +">User page +
+">Admin page + + \ No newline at end of file diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/userPage.jsp b/spring-mvc-forms/src/main/webapp/WEB-INF/views/userPage.jsp new file mode 100644 index 0000000000..4c1bd47502 --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/WEB-INF/views/userPage.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + +Insert title here + + +Welcome user! Logout +

+Back to links + + \ No newline at end of file From 4077ee29c50eebdecde96808ee97bbbdf8bd967e Mon Sep 17 00:00:00 2001 From: slavisa-baeldung Date: Tue, 7 Feb 2017 06:44:59 +0100 Subject: [PATCH 04/12] BAEL-639 - moving from test to main source tree --- guava/src/{test => main}/java/org/baeldung/guava/CustomEvent.java | 0 .../{test => main}/java/org/baeldung/guava/EventBusWrapper.java | 0 .../src/{test => main}/java/org/baeldung/guava/EventListener.java | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename guava/src/{test => main}/java/org/baeldung/guava/CustomEvent.java (100%) rename guava/src/{test => main}/java/org/baeldung/guava/EventBusWrapper.java (100%) rename guava/src/{test => main}/java/org/baeldung/guava/EventListener.java (100%) diff --git a/guava/src/test/java/org/baeldung/guava/CustomEvent.java b/guava/src/main/java/org/baeldung/guava/CustomEvent.java similarity index 100% rename from guava/src/test/java/org/baeldung/guava/CustomEvent.java rename to guava/src/main/java/org/baeldung/guava/CustomEvent.java diff --git a/guava/src/test/java/org/baeldung/guava/EventBusWrapper.java b/guava/src/main/java/org/baeldung/guava/EventBusWrapper.java similarity index 100% rename from guava/src/test/java/org/baeldung/guava/EventBusWrapper.java rename to guava/src/main/java/org/baeldung/guava/EventBusWrapper.java diff --git a/guava/src/test/java/org/baeldung/guava/EventListener.java b/guava/src/main/java/org/baeldung/guava/EventListener.java similarity index 100% rename from guava/src/test/java/org/baeldung/guava/EventListener.java rename to guava/src/main/java/org/baeldung/guava/EventListener.java From 178f49e4857a41f426330b29e155546904801852 Mon Sep 17 00:00:00 2001 From: Saptarshi Basu Date: Tue, 7 Feb 2017 15:27:52 +0530 Subject: [PATCH 05/12] BAEL-595 : Review comments incorporated (#1125) * WatchService vs. Apache Commons IO Mnitoring * Indentation fixed * Indentation fixed * JAX-RS API using Jersey [BAEL-558] * JAX-RS API using Jersey [BAEL-558] * Modifications made to remove xml * applicationContext.xml removed * All try catch moved to ExceptionMapper * fixes * review comments incorporated * module renamed * JAX-RS client [BAEL-595] * jersey-core dependency removed * assert changed to assertEquals * messagebody readers and writers removed * pom dependency corrected and other minor changes * Jersey version changed and toString() changed to valueOf() --- spring-jersey/pom.xml | 2 +- .../src/main/java/com/baeldung/client/rest/RestClient.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-jersey/pom.xml b/spring-jersey/pom.xml index 293850d41e..41ebb9a6b5 100644 --- a/spring-jersey/pom.xml +++ b/spring-jersey/pom.xml @@ -9,7 +9,7 @@ war - 2.25 + 2.25.1 1.7.22 1.1.8 4.12 diff --git a/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java b/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java index 0e45b68b14..34f7d45601 100644 --- a/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java +++ b/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java @@ -18,7 +18,7 @@ public class RestClient { } public Employee getJsonEmployee(int id) { - return client.target(REST_URI).path(new Integer(id).toString()).request(MediaType.APPLICATION_JSON).get(Employee.class); + return client.target(REST_URI).path(String.valueOf(id)).request(MediaType.APPLICATION_JSON).get(Employee.class); } public Response createXmlEmployee(Employee emp) { @@ -26,6 +26,6 @@ public class RestClient { } public Employee getXmlEmployee(int id) { - return client.target(REST_URI).path(new Integer(id).toString()).request(MediaType.APPLICATION_XML).get(Employee.class); + return client.target(REST_URI).path(String.valueOf(id)).request(MediaType.APPLICATION_XML).get(Employee.class); } } From c13453d77229fb18475d591ead7fe03e4484f642 Mon Sep 17 00:00:00 2001 From: Tryfon Date: Tue, 7 Feb 2017 12:36:06 +0200 Subject: [PATCH 06/12] Java 8 grouping by collector pull request (#1102) * Char array to string and string to char array test cases added * Minor code renames * Added groupingBy collector unit tests * Added test case for int summary calculation on grouped results * Added the grouping by classes to the main source path * Reverting char array to string test class * Reverting char array to string test class * Reverting char array to string test class * Reverting char array to string test class --- .../java_8_features/groupingby/BlogPost.java | 36 +++++ .../groupingby/BlogPostType.java | 5 + .../Java8GroupingByCollectorUnitTest.java | 132 ++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java create mode 100644 core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java create mode 100644 core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java diff --git a/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java new file mode 100644 index 0000000000..afc05e356a --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java @@ -0,0 +1,36 @@ +package com.baeldung.java_8_features.groupingby; + +public class BlogPost { + private String title; + private String author; + private BlogPostType type; + private int likes; + + public BlogPost(String title, String author, BlogPostType type, int likes) { + this.title = title; + this.author = author; + this.type = type; + this.likes = likes; + } + + public String getTitle() { + return title; + } + + public String getAuthor() { + return author; + } + + public BlogPostType getType() { + return type; + } + + public int getLikes() { + return likes; + } + + @Override + public String toString() { + return "BlogPost{" + "title='" + title + '\'' + ", type=" + type + ", likes=" + likes + '}'; + } +} diff --git a/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java new file mode 100644 index 0000000000..2029784e91 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java @@ -0,0 +1,5 @@ +package com.baeldung.java_8_features.groupingby; + +public enum BlogPostType { + NEWS, REVIEW, GUIDE +} diff --git a/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java new file mode 100644 index 0000000000..544db90b73 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java @@ -0,0 +1,132 @@ +package com.baeldung.java8; + +import org.junit.Test; + +import com.baeldung.java_8_features.groupingby.BlogPost; +import com.baeldung.java_8_features.groupingby.BlogPostType; + +import java.util.*; +import java.util.concurrent.ConcurrentMap; + +import static java.util.Comparator.comparingInt; +import static java.util.stream.Collectors.*; +import static org.junit.Assert.*; + +public class Java8GroupingByCollectorUnitTest { + + private static final List POSTS = Arrays.asList(new BlogPost("News item 1", "Author 1", BlogPostType.NEWS, 15), new BlogPost("Tech review 1", "Author 2", BlogPostType.REVIEW, 5), + new BlogPost("Programming guide", "Author 1", BlogPostType.GUIDE, 20), new BlogPost("News item 2", "Author 2", BlogPostType.NEWS, 35), new BlogPost("Tech review 2", "Author 1", BlogPostType.REVIEW, 15)); + + @Test + public void givenAListOfPosts_whenGroupedByType_thenGetAMapBetweenTypeAndPosts() { + Map> postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType)); + + assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); + assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); + assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndTheirTitlesAreJoinedInAString_thenGetAMapBetweenTypeAndCsvTitles() { + Map postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]")))); + + assertEquals("Post titles: [News item 1, News item 2]", postsPerType.get(BlogPostType.NEWS)); + assertEquals("Post titles: [Programming guide]", postsPerType.get(BlogPostType.GUIDE)); + assertEquals("Post titles: [Tech review 1, Tech review 2]", postsPerType.get(BlogPostType.REVIEW)); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndSumTheLikes_thenGetAMapBetweenTypeAndPostLikes() { + Map likesPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes))); + + assertEquals(50, likesPerType.get(BlogPostType.NEWS).intValue()); + assertEquals(20, likesPerType.get(BlogPostType.REVIEW).intValue()); + assertEquals(20, likesPerType.get(BlogPostType.GUIDE).intValue()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeInAnEnumMap_thenGetAnEnumMapBetweenTypeAndPosts() { + EnumMap> postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, () -> new EnumMap<>(BlogPostType.class), toList())); + + assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); + assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); + assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeInSets_thenGetAMapBetweenTypesAndSetsOfPosts() { + Map> postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, toSet())); + + assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); + assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); + assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeConcurrently_thenGetAMapBetweenTypeAndPosts() { + ConcurrentMap> postsPerType = POSTS.parallelStream().collect(groupingByConcurrent(BlogPost::getType)); + + assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); + assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); + assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndAveragingLikes_thenGetAMapBetweenTypeAndAverageNumberOfLikes() { + Map averageLikesPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes))); + + assertEquals(25, averageLikesPerType.get(BlogPostType.NEWS).intValue()); + assertEquals(20, averageLikesPerType.get(BlogPostType.GUIDE).intValue()); + assertEquals(10, averageLikesPerType.get(BlogPostType.REVIEW).intValue()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndCounted_thenGetAMapBetweenTypeAndNumberOfPosts() { + Map numberOfPostsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, counting())); + + assertEquals(2, numberOfPostsPerType.get(BlogPostType.NEWS).intValue()); + assertEquals(1, numberOfPostsPerType.get(BlogPostType.GUIDE).intValue()); + assertEquals(2, numberOfPostsPerType.get(BlogPostType.REVIEW).intValue()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndMaxingLikes_thenGetAMapBetweenTypeAndMaximumNumberOfLikes() { + Map> maxLikesPerPostType = POSTS.stream().collect(groupingBy(BlogPost::getType, maxBy(comparingInt(BlogPost::getLikes)))); + + assertTrue(maxLikesPerPostType.get(BlogPostType.NEWS).isPresent()); + assertEquals(35, maxLikesPerPostType.get(BlogPostType.NEWS).get().getLikes()); + + assertTrue(maxLikesPerPostType.get(BlogPostType.GUIDE).isPresent()); + assertEquals(20, maxLikesPerPostType.get(BlogPostType.GUIDE).get().getLikes()); + + assertTrue(maxLikesPerPostType.get(BlogPostType.REVIEW).isPresent()); + assertEquals(15, maxLikesPerPostType.get(BlogPostType.REVIEW).get().getLikes()); + } + + @Test + public void givenAListOfPosts_whenGroupedByAuthorAndThenByType_thenGetAMapBetweenAuthorAndMapsBetweenTypeAndBlogPosts() { + Map>> map = POSTS.stream().collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType))); + + assertEquals(1, map.get("Author 1").get(BlogPostType.NEWS).size()); + assertEquals(1, map.get("Author 1").get(BlogPostType.GUIDE).size()); + assertEquals(1, map.get("Author 1").get(BlogPostType.REVIEW).size()); + + assertEquals(1, map.get("Author 2").get(BlogPostType.NEWS).size()); + assertEquals(1, map.get("Author 2").get(BlogPostType.REVIEW).size()); + assertNull(map.get("Author 2").get(BlogPostType.GUIDE)); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBetweenTypeAndSummary() { + Map likeStatisticsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, summarizingInt(BlogPost::getLikes))); + + IntSummaryStatistics newsLikeStatistics = likeStatisticsPerType.get(BlogPostType.NEWS); + + assertEquals(2, newsLikeStatistics.getCount()); + assertEquals(50, newsLikeStatistics.getSum()); + assertEquals(25.0, newsLikeStatistics.getAverage(), 0.001); + assertEquals(35, newsLikeStatistics.getMax()); + assertEquals(15, newsLikeStatistics.getMin()); + } + +} From fc233b4be7950b0df7f1a1dd88a515581519621f Mon Sep 17 00:00:00 2001 From: Sunil Mogadati Date: Tue, 7 Feb 2017 03:44:17 -0700 Subject: [PATCH 07/12] Formatting change using Baeldung formatter --- .../Java8GroupingByCollectorUnitTest.java | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java index 544db90b73..178cd72542 100644 --- a/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java +++ b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java @@ -1,17 +1,35 @@ package com.baeldung.java8; +import static java.util.Comparator.comparingInt; +import static java.util.stream.Collectors.averagingInt; +import static java.util.stream.Collectors.counting; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.groupingByConcurrent; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.maxBy; +import static java.util.stream.Collectors.summarizingInt; +import static java.util.stream.Collectors.summingInt; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.IntSummaryStatistics; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + import org.junit.Test; import com.baeldung.java_8_features.groupingby.BlogPost; import com.baeldung.java_8_features.groupingby.BlogPostType; -import java.util.*; -import java.util.concurrent.ConcurrentMap; - -import static java.util.Comparator.comparingInt; -import static java.util.stream.Collectors.*; -import static org.junit.Assert.*; - public class Java8GroupingByCollectorUnitTest { private static final List POSTS = Arrays.asList(new BlogPost("News item 1", "Author 1", BlogPostType.NEWS, 15), new BlogPost("Tech review 1", "Author 2", BlogPostType.REVIEW, 5), @@ -119,9 +137,9 @@ public class Java8GroupingByCollectorUnitTest { @Test public void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBetweenTypeAndSummary() { Map likeStatisticsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, summarizingInt(BlogPost::getLikes))); - + IntSummaryStatistics newsLikeStatistics = likeStatisticsPerType.get(BlogPostType.NEWS); - + assertEquals(2, newsLikeStatistics.getCount()); assertEquals(50, newsLikeStatistics.getSum()); assertEquals(25.0, newsLikeStatistics.getAverage(), 0.001); From 3559789573f612be3911eb983bf51abed125c5c0 Mon Sep 17 00:00:00 2001 From: Pedja Date: Tue, 7 Feb 2017 11:54:48 +0100 Subject: [PATCH 08/12] BAEL-677 Small refactoring --- .../ConcurrentModificationUnitTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) rename core-java/src/test/java/com/baeldung/java/{concurrentmodificationexception => concurrentmodification}/ConcurrentModificationUnitTest.java (81%) diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java similarity index 81% rename from core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java rename to core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java index 11c6012ecd..d16a1fcdf4 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmodificationexception/ConcurrentModificationUnitTest.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java @@ -1,6 +1,5 @@ -package com.baeldung.java.concurrentmodificationexception; +package com.baeldung.java.concurrentmodification; -import org.assertj.core.api.Assertions; import org.junit.Test; import java.util.ArrayList; @@ -22,7 +21,7 @@ public class ConcurrentModificationUnitTest { } @Test - public void givenIterating_whenUsingIteratorRemove_thenDontError() throws InterruptedException { + public void givenIterating_whenUsingIteratorRemove_thenNoError() throws InterruptedException { ArrayList integers = newArrayList(1, 2, 3); @@ -37,7 +36,7 @@ public class ConcurrentModificationUnitTest { } @Test - public void givenIterating_whenUsingRemovalList_thenDontError() throws InterruptedException { + public void givenIterating_whenUsingRemovalList_thenNoError() throws InterruptedException { ArrayList integers = newArrayList(1, 2, 3); ArrayList toRemove = newArrayList(); @@ -57,7 +56,7 @@ public class ConcurrentModificationUnitTest { ArrayList integers = newArrayList(1, 2, 3); - integers.removeIf((i) -> i == 2); + integers.removeIf(i -> i == 2); assertThat(integers).containsExactly(1, 3); } From 92ad8123f1288f051fe20b4cbd331a4a41867ba6 Mon Sep 17 00:00:00 2001 From: pivovarit Date: Tue, 7 Feb 2017 19:32:09 +0100 Subject: [PATCH 09/12] Refactor Java8GroupingByCollectorUnitTest --- .../Java8GroupingByCollectorUnitTest.java | 227 ++++++++++++------ 1 file changed, 154 insertions(+), 73 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java index 178cd72542..4452b4db9a 100644 --- a/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java +++ b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java @@ -1,52 +1,47 @@ package com.baeldung.java8; -import static java.util.Comparator.comparingInt; -import static java.util.stream.Collectors.averagingInt; -import static java.util.stream.Collectors.counting; -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.groupingByConcurrent; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.mapping; -import static java.util.stream.Collectors.maxBy; -import static java.util.stream.Collectors.summarizingInt; -import static java.util.stream.Collectors.summingInt; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.EnumMap; -import java.util.IntSummaryStatistics; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; - -import org.junit.Test; - import com.baeldung.java_8_features.groupingby.BlogPost; import com.baeldung.java_8_features.groupingby.BlogPostType; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ConcurrentMap; + +import static java.util.Comparator.comparingInt; +import static java.util.stream.Collectors.*; +import static org.junit.Assert.*; public class Java8GroupingByCollectorUnitTest { - private static final List POSTS = Arrays.asList(new BlogPost("News item 1", "Author 1", BlogPostType.NEWS, 15), new BlogPost("Tech review 1", "Author 2", BlogPostType.REVIEW, 5), - new BlogPost("Programming guide", "Author 1", BlogPostType.GUIDE, 20), new BlogPost("News item 2", "Author 2", BlogPostType.NEWS, 35), new BlogPost("Tech review 2", "Author 1", BlogPostType.REVIEW, 15)); + private static final List posts = Arrays.asList( + new BlogPost("News item 1", "Author 1", BlogPostType.NEWS, 15), + new BlogPost("Tech review 1", "Author 2", BlogPostType.REVIEW, 5), + new BlogPost("Programming guide", "Author 1", BlogPostType.GUIDE, 20), + new BlogPost("News item 2", "Author 2", BlogPostType.NEWS, 35), + new BlogPost("Tech review 2", "Author 1", BlogPostType.REVIEW, 15)); @Test public void givenAListOfPosts_whenGroupedByType_thenGetAMapBetweenTypeAndPosts() { - Map> postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType)); + Map> postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType)); - assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); - assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); - assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); } @Test public void givenAListOfPosts_whenGroupedByTypeAndTheirTitlesAreJoinedInAString_thenGetAMapBetweenTypeAndCsvTitles() { - Map postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]")))); + Map postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]")))); assertEquals("Post titles: [News item 1, News item 2]", postsPerType.get(BlogPostType.NEWS)); assertEquals("Post titles: [Programming guide]", postsPerType.get(BlogPostType.GUIDE)); @@ -55,88 +50,174 @@ public class Java8GroupingByCollectorUnitTest { @Test public void givenAListOfPosts_whenGroupedByTypeAndSumTheLikes_thenGetAMapBetweenTypeAndPostLikes() { - Map likesPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes))); + Map likesPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes))); - assertEquals(50, likesPerType.get(BlogPostType.NEWS).intValue()); - assertEquals(20, likesPerType.get(BlogPostType.REVIEW).intValue()); - assertEquals(20, likesPerType.get(BlogPostType.GUIDE).intValue()); + assertEquals(50, likesPerType + .get(BlogPostType.NEWS) + .intValue()); + assertEquals(20, likesPerType + .get(BlogPostType.REVIEW) + .intValue()); + assertEquals(20, likesPerType + .get(BlogPostType.GUIDE) + .intValue()); } @Test public void givenAListOfPosts_whenGroupedByTypeInAnEnumMap_thenGetAnEnumMapBetweenTypeAndPosts() { - EnumMap> postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, () -> new EnumMap<>(BlogPostType.class), toList())); + EnumMap> postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, () -> new EnumMap<>(BlogPostType.class), toList())); - assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); - assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); - assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); } @Test public void givenAListOfPosts_whenGroupedByTypeInSets_thenGetAMapBetweenTypesAndSetsOfPosts() { - Map> postsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, toSet())); + Map> postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, toSet())); - assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); - assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); - assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); } @Test public void givenAListOfPosts_whenGroupedByTypeConcurrently_thenGetAMapBetweenTypeAndPosts() { - ConcurrentMap> postsPerType = POSTS.parallelStream().collect(groupingByConcurrent(BlogPost::getType)); + ConcurrentMap> postsPerType = posts + .parallelStream() + .collect(groupingByConcurrent(BlogPost::getType)); - assertEquals(2, postsPerType.get(BlogPostType.NEWS).size()); - assertEquals(1, postsPerType.get(BlogPostType.GUIDE).size()); - assertEquals(2, postsPerType.get(BlogPostType.REVIEW).size()); + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); } @Test public void givenAListOfPosts_whenGroupedByTypeAndAveragingLikes_thenGetAMapBetweenTypeAndAverageNumberOfLikes() { - Map averageLikesPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes))); + Map averageLikesPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes))); - assertEquals(25, averageLikesPerType.get(BlogPostType.NEWS).intValue()); - assertEquals(20, averageLikesPerType.get(BlogPostType.GUIDE).intValue()); - assertEquals(10, averageLikesPerType.get(BlogPostType.REVIEW).intValue()); + assertEquals(25, averageLikesPerType + .get(BlogPostType.NEWS) + .intValue()); + assertEquals(20, averageLikesPerType + .get(BlogPostType.GUIDE) + .intValue()); + assertEquals(10, averageLikesPerType + .get(BlogPostType.REVIEW) + .intValue()); } @Test public void givenAListOfPosts_whenGroupedByTypeAndCounted_thenGetAMapBetweenTypeAndNumberOfPosts() { - Map numberOfPostsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, counting())); + Map numberOfPostsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, counting())); - assertEquals(2, numberOfPostsPerType.get(BlogPostType.NEWS).intValue()); - assertEquals(1, numberOfPostsPerType.get(BlogPostType.GUIDE).intValue()); - assertEquals(2, numberOfPostsPerType.get(BlogPostType.REVIEW).intValue()); + assertEquals(2, numberOfPostsPerType + .get(BlogPostType.NEWS) + .intValue()); + assertEquals(1, numberOfPostsPerType + .get(BlogPostType.GUIDE) + .intValue()); + assertEquals(2, numberOfPostsPerType + .get(BlogPostType.REVIEW) + .intValue()); } @Test public void givenAListOfPosts_whenGroupedByTypeAndMaxingLikes_thenGetAMapBetweenTypeAndMaximumNumberOfLikes() { - Map> maxLikesPerPostType = POSTS.stream().collect(groupingBy(BlogPost::getType, maxBy(comparingInt(BlogPost::getLikes)))); + Map> maxLikesPerPostType = posts + .stream() + .collect(groupingBy(BlogPost::getType, maxBy(comparingInt(BlogPost::getLikes)))); - assertTrue(maxLikesPerPostType.get(BlogPostType.NEWS).isPresent()); - assertEquals(35, maxLikesPerPostType.get(BlogPostType.NEWS).get().getLikes()); + assertTrue(maxLikesPerPostType + .get(BlogPostType.NEWS) + .isPresent()); + assertEquals(35, maxLikesPerPostType + .get(BlogPostType.NEWS) + .get() + .getLikes()); - assertTrue(maxLikesPerPostType.get(BlogPostType.GUIDE).isPresent()); - assertEquals(20, maxLikesPerPostType.get(BlogPostType.GUIDE).get().getLikes()); + assertTrue(maxLikesPerPostType + .get(BlogPostType.GUIDE) + .isPresent()); + assertEquals(20, maxLikesPerPostType + .get(BlogPostType.GUIDE) + .get() + .getLikes()); - assertTrue(maxLikesPerPostType.get(BlogPostType.REVIEW).isPresent()); - assertEquals(15, maxLikesPerPostType.get(BlogPostType.REVIEW).get().getLikes()); + assertTrue(maxLikesPerPostType + .get(BlogPostType.REVIEW) + .isPresent()); + assertEquals(15, maxLikesPerPostType + .get(BlogPostType.REVIEW) + .get() + .getLikes()); } @Test public void givenAListOfPosts_whenGroupedByAuthorAndThenByType_thenGetAMapBetweenAuthorAndMapsBetweenTypeAndBlogPosts() { - Map>> map = POSTS.stream().collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType))); + Map>> map = posts + .stream() + .collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType))); - assertEquals(1, map.get("Author 1").get(BlogPostType.NEWS).size()); - assertEquals(1, map.get("Author 1").get(BlogPostType.GUIDE).size()); - assertEquals(1, map.get("Author 1").get(BlogPostType.REVIEW).size()); + assertEquals(1, map + .get("Author 1") + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, map + .get("Author 1") + .get(BlogPostType.GUIDE) + .size()); + assertEquals(1, map + .get("Author 1") + .get(BlogPostType.REVIEW) + .size()); - assertEquals(1, map.get("Author 2").get(BlogPostType.NEWS).size()); - assertEquals(1, map.get("Author 2").get(BlogPostType.REVIEW).size()); - assertNull(map.get("Author 2").get(BlogPostType.GUIDE)); + assertEquals(1, map + .get("Author 2") + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, map + .get("Author 2") + .get(BlogPostType.REVIEW) + .size()); + assertNull(map + .get("Author 2") + .get(BlogPostType.GUIDE)); } @Test public void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBetweenTypeAndSummary() { - Map likeStatisticsPerType = POSTS.stream().collect(groupingBy(BlogPost::getType, summarizingInt(BlogPost::getLikes))); + Map likeStatisticsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, summarizingInt(BlogPost::getLikes))); IntSummaryStatistics newsLikeStatistics = likeStatisticsPerType.get(BlogPostType.NEWS); From a9d8c5f3a3154125cf90eef0541963a8ce0c2b4b Mon Sep 17 00:00:00 2001 From: Danil Kornishev Date: Tue, 7 Feb 2017 14:34:10 -0500 Subject: [PATCH 10/12] Introduction to Neo4j (#1098) * Nashorn * Nashorn x2 * Nashorn added trailing newlines * Cleanup * Formatted script lines * Change system outs to asserts * Change Nashorn to be Junit tests * Remove empty test * Added Neo4j section * Revert NashornTest --- core-java/pom.xml | 44 ++++- .../src/main/java/com/baeldung/graph/Car.java | 50 ++++++ .../main/java/com/baeldung/graph/Company.java | 45 +++++ .../com/baeldung/graph/Neo4JServerTest.java | 60 +++++++ .../java/com/baeldung/graph/Neo4jOgmTest.java | 46 +++++ .../java/com/baeldung/graph/Neo4jTest.java | 167 ++++++++++++++++++ 6 files changed, 409 insertions(+), 3 deletions(-) create mode 100644 core-java/src/main/java/com/baeldung/graph/Car.java create mode 100644 core-java/src/main/java/com/baeldung/graph/Company.java create mode 100644 core-java/src/test/java/com/baeldung/graph/Neo4JServerTest.java create mode 100644 core-java/src/test/java/com/baeldung/graph/Neo4jOgmTest.java create mode 100644 core-java/src/test/java/com/baeldung/graph/Neo4jTest.java diff --git a/core-java/pom.xml b/core-java/pom.xml index 85afee2968..1a3034b860 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung core-java @@ -10,6 +10,44 @@ + + org.neo4j + neo4j + 3.1.0 + + + + org.neo4j.driver + neo4j-java-driver + 1.1.1 + + + + org.neo4j + neo4j-jdbc-driver + 3.0.1 + + + + org.neo4j + neo4j-ogm-core + 2.1.1 + + + + org.neo4j + neo4j-ogm-embedded-driver + 2.1.1 + + + + com.google.inject + guice + 4.1.0 + no_aop + test + + net.sourceforge.collections @@ -63,7 +101,6 @@ grep4j ${grep4j.version} - @@ -263,7 +300,8 @@ true - + org.baeldung.executable.ExecutableMavenJar diff --git a/core-java/src/main/java/com/baeldung/graph/Car.java b/core-java/src/main/java/com/baeldung/graph/Car.java new file mode 100644 index 0000000000..1dc65a0d4b --- /dev/null +++ b/core-java/src/main/java/com/baeldung/graph/Car.java @@ -0,0 +1,50 @@ +package com.baeldung.graph; + +import org.neo4j.ogm.annotation.GraphId; +import org.neo4j.ogm.annotation.NodeEntity; +import org.neo4j.ogm.annotation.Relationship; + +/** + * @author Danil Kornishev (danil.kornishev@mastercard.com) + */ +@NodeEntity +public class Car { + @GraphId + private Long id; + + private String make; + + @Relationship(direction = "INCOMING") + private Company company; + + public Car(String make, String model) { + this.make = make; + this.model = model; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + private String model; +} diff --git a/core-java/src/main/java/com/baeldung/graph/Company.java b/core-java/src/main/java/com/baeldung/graph/Company.java new file mode 100644 index 0000000000..1fe892b331 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/graph/Company.java @@ -0,0 +1,45 @@ +package com.baeldung.graph; + +import org.neo4j.ogm.annotation.NodeEntity; +import org.neo4j.ogm.annotation.Relationship; + +/** + * @author Danil Kornishev (danil.kornishev@mastercard.com) + */ +@NodeEntity +public class Company { + private Long id; + + private String name; + + @Relationship(type="owns") + private Car car; + + public Company(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Car getCar() { + return car; + } + + public void setCar(Car car) { + this.car = car; + } +} diff --git a/core-java/src/test/java/com/baeldung/graph/Neo4JServerTest.java b/core-java/src/test/java/com/baeldung/graph/Neo4JServerTest.java new file mode 100644 index 0000000000..b41588b71e --- /dev/null +++ b/core-java/src/test/java/com/baeldung/graph/Neo4JServerTest.java @@ -0,0 +1,60 @@ +package com.baeldung.graph; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +import org.junit.Ignore; +import org.junit.Test; +import org.neo4j.driver.v1.AuthTokens; +import org.neo4j.driver.v1.Driver; +import org.neo4j.driver.v1.GraphDatabase; +import org.neo4j.driver.v1.Session; +import org.neo4j.driver.v1.StatementResult; +import org.testng.Assert; + +@Ignore +public class Neo4JServerTest { + + @Test + public void standAloneDriver() { + Driver driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "12345")); + Session session = driver.session(); + + session.run("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + StatementResult result = session.run("MATCH (company:Company)-[:owns]-> (car:Car)" + + "WHERE car.make='tesla' and car.model='modelX'" + + "RETURN company.name"); + + Assert.assertTrue(result.hasNext()); + Assert.assertEquals(result.next().get("company.name").asString(), "Baeldung"); + + session.close(); + driver.close(); + } + + @Test + public void standAloneJdbc() throws Exception { + Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://localhost/?user=neo4j,password=12345,scheme=basic"); + + // Querying + try (Statement stmt = con.createStatement()) { + stmt.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + ResultSet rs = stmt.executeQuery("MATCH (company:Company)-[:owns]-> (car:Car)" + + "WHERE car.make='tesla' and car.model='modelX'" + + "RETURN company.name"); + + while (rs.next()) { + Assert.assertEquals(rs.getString("company.name"), "Baeldung"); + } + } + con.close(); + } +} diff --git a/core-java/src/test/java/com/baeldung/graph/Neo4jOgmTest.java b/core-java/src/test/java/com/baeldung/graph/Neo4jOgmTest.java new file mode 100644 index 0000000000..00bd47d029 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/graph/Neo4jOgmTest.java @@ -0,0 +1,46 @@ +package com.baeldung.graph; + +import org.junit.Test; +import org.neo4j.ogm.config.Configuration; +import org.neo4j.ogm.model.Result; +import org.neo4j.ogm.session.Session; +import org.neo4j.ogm.session.SessionFactory; +import org.testng.Assert; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Danil Kornishev (danil.kornishev@mastercard.com) + */ +public class Neo4jOgmTest { + + @Test + public void testOgm() { + Configuration conf = new Configuration(); + conf.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver"); + + SessionFactory factory = new SessionFactory(conf, "com.baeldung.graph"); + Session session = factory.openSession(); + + Car tesla = new Car("tesla", "modelS"); + Company baeldung = new Company("baeldung"); + + baeldung.setCar(tesla); + + session.save(baeldung); + + Map params = new HashMap<>(); + params.put("make", "tesla"); + Result result = session.query("MATCH (car:Car) <-[:owns]- (company:Company)" + + " WHERE car.make=$make" + + " RETURN company", params); + + Map firstResult = result.iterator().next(); + + Assert.assertEquals(firstResult.size(), 1); + + Company actual = (Company) firstResult.get("company"); + Assert.assertEquals(actual.getName(), baeldung.getName()); + } +} diff --git a/core-java/src/test/java/com/baeldung/graph/Neo4jTest.java b/core-java/src/test/java/com/baeldung/graph/Neo4jTest.java new file mode 100644 index 0000000000..6956c2c39f --- /dev/null +++ b/core-java/src/test/java/com/baeldung/graph/Neo4jTest.java @@ -0,0 +1,167 @@ +package com.baeldung.graph; + + +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Label; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.NotFoundException; +import org.neo4j.graphdb.RelationshipType; +import org.neo4j.graphdb.Result; +import org.neo4j.graphdb.factory.GraphDatabaseFactory; +import org.testng.Assert; + +public class Neo4jTest { + + private static GraphDatabaseService graphDb; + + @Before + public void setUp() { + GraphDatabaseFactory graphDbFactory = new GraphDatabaseFactory(); + graphDb = graphDbFactory.newEmbeddedDatabase(new File("data/cars")); + } + + @After + public void tearDown() { + graphDb.shutdown(); + } + + @Test + public void testPersonCar() { + graphDb.beginTx(); + Node car = graphDb.createNode(Label.label("Car")); + car.setProperty("make", "tesla"); + car.setProperty("model", "model3"); + + Node owner = graphDb.createNode(Label.label("Person")); + owner.setProperty("firstName", "baeldung"); + owner.setProperty("lastName", "baeldung"); + + owner.createRelationshipTo(car, RelationshipType.withName("owner")); + + Result result = graphDb.execute("MATCH (c:Car) <-[owner]- (p:Person) " + + "WHERE c.make = 'tesla'" + + "RETURN p.firstName, p.lastName"); + + Map firstResult = result.next(); + Assert.assertEquals("baeldung", firstResult.get("p.firstName")); + } + + @Test + public void testCreateNode() { + + graphDb.beginTx(); + + Result result = graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"})" + + "RETURN baeldung"); + + Map firstResult = result.next(); + Node firstNode = (Node) firstResult.get("baeldung"); + Assert.assertEquals(firstNode.getProperty("name"), "Baeldung"); + } + + @Test + public void testCreateNodeAndLink() { + graphDb.beginTx(); + + Result result = graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + Map firstResult = result.next(); + Assert.assertTrue(firstResult.containsKey("baeldung")); + Assert.assertTrue(firstResult.containsKey("tesla")); + } + + @Test + public void testFindAndReturn() { + graphDb.beginTx(); + + graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + Result result = graphDb.execute("MATCH (company:Company)-[:owns]-> (car:Car)" + + "WHERE car.make='tesla' and car.model='modelX'" + + "RETURN company.name"); + + Map firstResult = result.next(); + Assert.assertEquals(firstResult.get("company.name"), "Baeldung"); + } + + @Test + public void testUpdate() { + graphDb.beginTx(); + + graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + Result result = graphDb.execute("MATCH (car:Car)" + + "WHERE car.make='tesla'" + + " SET car.milage=120" + + " SET car :Car:Electro" + + " SET car.model=NULL" + + " RETURN car"); + + Map firstResult = result.next(); + Node car = (Node) firstResult.get("car"); + + Assert.assertEquals(car.getProperty("milage"), 120L); + Assert.assertEquals(car.getLabels(), Arrays.asList(Label.label("Car"), Label.label("Electro"))); + + try { + car.getProperty("model"); + Assert.fail(); + } catch (NotFoundException e) { + // expected + } + } + + @Test + public void testDelete() { + graphDb.beginTx(); + + graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + graphDb.execute("MATCH (company:Company)" + + " WHERE company.name='Baeldung'" + + " DELETE company"); + + Result result = graphDb.execute("MATCH (company:Company)" + + " WHERE company.name='Baeldung'" + + " RETURN company"); + + Assert.assertFalse(result.hasNext()); + } + + @Test + public void testBindings() { + graphDb.beginTx(); + + Map params = new HashMap<>(); + params.put("name", "baeldung"); + params.put("make", "tesla"); + params.put("model", "modelS"); + + Result result = graphDb.execute("CREATE (baeldung:Company {name:$name}) " + + "-[:owns]-> (tesla:Car {make: $make, model: $model})" + + "RETURN baeldung, tesla", params); + + Map firstResult = result.next(); + Assert.assertTrue(firstResult.containsKey("baeldung")); + Assert.assertTrue(firstResult.containsKey("tesla")); + + Node car = (Node) firstResult.get("tesla"); + Assert.assertEquals(car.getProperty("model"), "modelS"); + } +} From 5c8acbac57c08b2217d36c64abfea4cde4a8ac63 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Tue, 7 Feb 2017 21:12:14 +0000 Subject: [PATCH 11/12] Added stream removal from collection (#1131) --- .../ConcurrentModificationUnitTest.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java index d16a1fcdf4..f7a7bd5fe0 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java @@ -3,9 +3,12 @@ package com.baeldung.java.concurrentmodification; import org.junit.Test; import java.util.ArrayList; +import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Iterator; +import java.util.List; +import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Lists.newArrayList; @@ -13,7 +16,7 @@ public class ConcurrentModificationUnitTest { @Test(expected = ConcurrentModificationException.class) public void givenIterating_whenRemoving_thenThrowException() throws InterruptedException { - ArrayList integers = newArrayList(1, 2, 3); + List integers = newArrayList(1, 2, 3); for (Integer integer : integers) { integers.remove(1); @@ -23,7 +26,7 @@ public class ConcurrentModificationUnitTest { @Test public void givenIterating_whenUsingIteratorRemove_thenNoError() throws InterruptedException { - ArrayList integers = newArrayList(1, 2, 3); + List integers = newArrayList(1, 2, 3); for (Iterator iterator = integers.iterator(); iterator.hasNext();) { Integer integer = iterator.next(); @@ -38,8 +41,8 @@ public class ConcurrentModificationUnitTest { @Test public void givenIterating_whenUsingRemovalList_thenNoError() throws InterruptedException { - ArrayList integers = newArrayList(1, 2, 3); - ArrayList toRemove = newArrayList(); + List integers = newArrayList(1, 2, 3); + List toRemove = newArrayList(); for (Integer integer : integers) { if(integer == 2) { @@ -54,10 +57,24 @@ public class ConcurrentModificationUnitTest { @Test public void whenUsingRemoveIf_thenRemoveElements() throws InterruptedException { - ArrayList integers = newArrayList(1, 2, 3); + Collection integers = newArrayList(1, 2, 3); integers.removeIf(i -> i == 2); assertThat(integers).containsExactly(1, 3); } + + @Test + public void whenUsingStream_thenRemoveElements() { + Collection integers = newArrayList(1, 2, 3); + + List collected = integers + .stream() + .filter(i -> i != 2) + .map(Object::toString) + .collect(toList()); + + assertThat(collected).containsExactly("1", "3"); + } + } From 40a22badfce648940016a90d6668fa2ee8458298 Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Tue, 7 Feb 2017 19:39:27 -0600 Subject: [PATCH 12/12] Update README.md --- apache-poi/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apache-poi/README.md b/apache-poi/README.md index cef6810c97..10fe8ba2e7 100644 --- a/apache-poi/README.md +++ b/apache-poi/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Microsoft Word Processing in Java with Apache POI](http://www.baeldung.com/java-microsoft-word-with-apache-poi) +- [Working with Microsoft Excel in Java](http://www.baeldung.com/java-microsoft-excel)