From 085825e149305b38f9f397f85f8f69cad7060692 Mon Sep 17 00:00:00 2001 From: Varun Upadhyay Date: Thu, 1 Nov 2018 18:18:10 -0700 Subject: [PATCH 1/5] Fixed a bug in findWord method --- .../com/baeldung/string/searching/WordIndexer.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/searching/WordIndexer.java b/java-strings/src/main/java/com/baeldung/string/searching/WordIndexer.java index 5314efb0b4..1bcad6dd32 100644 --- a/java-strings/src/main/java/com/baeldung/string/searching/WordIndexer.java +++ b/java-strings/src/main/java/com/baeldung/string/searching/WordIndexer.java @@ -11,11 +11,14 @@ public class WordIndexer { String lowerCaseTextString = textString.toLowerCase(); String lowerCaseWord = word.toLowerCase(); - while(index != -1){ - index = lowerCaseTextString.indexOf(lowerCaseWord, index + 1); - if (index != -1) { - indexes.add(index); + while(index != -1) { + index = lowerCaseTextString.indexOf(lowerCaseWord, index); + if (index == -1) { + break; } + + indexes.add(index); + index++; } return indexes; } From adacecbd758459b2d890009ca31d7342683bf260 Mon Sep 17 00:00:00 2001 From: Shreyas Mahajan Date: Fri, 2 Nov 2018 11:54:23 +0530 Subject: [PATCH 2/5] BAEL-2201-shreyas-Replacing customer written MockitoExtension class with mockito's own --- testing-modules/junit-5/pom.xml | 13 +++- .../junit5/mockito/MockitoExtension.java | 75 ------------------- .../junit5/mockito/UserServiceUnitTest.java | 19 ++--- 3 files changed, 18 insertions(+), 89 deletions(-) delete mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/MockitoExtension.java diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index 93365264ac..b7600267d9 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -72,6 +72,13 @@ + + org.mockito + mockito-junit-jupiter + ${mockito.junit.jupiter.version} + test + + org.powermock powermock-api-mockito2 @@ -118,13 +125,13 @@ - 5.2.0 + 5.3.1 + 2.23.0 1.2.0 5.2.0 2.8.2 1.4.196 - 2.8.9 - 1.7.4 + 2.0.0-RC.1 2.21.0 1.6.0 5.0.1.RELEASE diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/MockitoExtension.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/MockitoExtension.java deleted file mode 100644 index 5836ef46e6..0000000000 --- a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/MockitoExtension.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2015-2016 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v1.0 which - * accompanies this distribution and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - -package com.baeldung.junit5.mockito; - -import static org.mockito.Mockito.mock; - -import java.lang.reflect.Parameter; - -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.ExtensionContext.Namespace; -import org.junit.jupiter.api.extension.ExtensionContext.Store; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.api.extension.ParameterResolver; -import org.junit.jupiter.api.extension.TestInstancePostProcessor; -import org.mockito.MockitoAnnotations; -import org.mockito.Mock; - -/** - * {@code MockitoExtension} showcases the {@link TestInstancePostProcessor} - * and {@link ParameterResolver} extension APIs of JUnit 5 by providing - * dependency injection support at the field level and at the method parameter - * level via Mockito 2.x's {@link Mock @Mock} annotation. - * - * @since 5.0 - */ -public class MockitoExtension implements TestInstancePostProcessor, ParameterResolver { - - @Override - public void postProcessTestInstance(Object testInstance, ExtensionContext context) { - MockitoAnnotations.initMocks(testInstance); - } - - @Override - public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { - return parameterContext.getParameter().isAnnotationPresent(Mock.class); - } - - @Override - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { - return getMock(parameterContext.getParameter(), extensionContext); - } - - private Object getMock(Parameter parameter, ExtensionContext extensionContext) { - Class mockType = parameter.getType(); - Store mocks = extensionContext.getStore(Namespace.create(MockitoExtension.class, mockType)); - String mockName = getMockName(parameter); - - if (mockName != null) { - return mocks.getOrComputeIfAbsent(mockName, key -> mock(mockType, mockName)); - } - else { - return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(), key -> mock(mockType)); - } - } - - private String getMockName(Parameter parameter) { - String explicitMockName = parameter.getAnnotation(Mock.class).name().trim(); - if (!explicitMockName.isEmpty()) { - return explicitMockName; - } - else if (parameter.isNamePresent()) { - return parameter.getName(); - } - return null; - } - -} \ No newline at end of file diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java index 1ddab0531a..2e94072e79 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java @@ -3,19 +3,16 @@ package com.baeldung.junit5.mockito; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.platform.runner.JUnitPlatform; -import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; +import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.stubbing.Answer; import com.baeldung.junit5.mockito.repository.MailClient; @@ -25,25 +22,25 @@ import com.baeldung.junit5.mockito.service.DefaultUserService; import com.baeldung.junit5.mockito.service.Errors; import com.baeldung.junit5.mockito.service.UserService; -@RunWith(JUnitPlatform.class) @ExtendWith(MockitoExtension.class) public class UserServiceUnitTest { UserService userService; @Mock UserRepository userRepository; - + @Mock MailClient mailClient; + User user; @BeforeEach - void init(@Mock SettingRepository settingRepository, @Mock MailClient mailClient) { + void init(@Mock SettingRepository settingRepository) { userService = new DefaultUserService(userRepository, settingRepository, mailClient); - when(settingRepository.getUserMinAge()).thenReturn(10); + lenient().when(settingRepository.getUserMinAge()).thenReturn(10); when(settingRepository.getUserNameMinLength()).thenReturn(4); - when(userRepository.isUsernameAlreadyExists(any(String.class))).thenReturn(false); + lenient().when(userRepository.isUsernameAlreadyExists(any(String.class))).thenReturn(false); } @Test - void givenValidUser_whenSaveUser_thenSucceed(@Mock MailClient mailClient) { + void givenValidUser_whenSaveUser_thenSucceed() { // Given user = new User("Jerry", 12); when(userRepository.insert(any(User.class))).then(new Answer() { From 9604defd6c20b103cecc1fa333e770ab39adcf54 Mon Sep 17 00:00:00 2001 From: Shreyas Mahajan Date: Fri, 2 Nov 2018 14:55:16 +0530 Subject: [PATCH 3/5] BAEL-2201-shreyas-Minor changes to reflect the code used in article. --- .../baeldung/junit5/mockito/UserServiceUnitTest.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java index 2e94072e79..d4195e3b12 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/mockito/UserServiceUnitTest.java @@ -9,6 +9,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; @@ -23,9 +25,11 @@ import com.baeldung.junit5.mockito.service.Errors; import com.baeldung.junit5.mockito.service.UserService; @ExtendWith(MockitoExtension.class) +@RunWith(JUnitPlatform.class) public class UserServiceUnitTest { UserService userService; + SettingRepository settingRepository; @Mock UserRepository userRepository; @Mock MailClient mailClient; @@ -37,10 +41,11 @@ public class UserServiceUnitTest { lenient().when(settingRepository.getUserMinAge()).thenReturn(10); when(settingRepository.getUserNameMinLength()).thenReturn(4); lenient().when(userRepository.isUsernameAlreadyExists(any(String.class))).thenReturn(false); + this.settingRepository = settingRepository; } @Test - void givenValidUser_whenSaveUser_thenSucceed() { + void givenValidUser_whenSaveUser_thenSucceed(@Mock MailClient mailClient) { // Given user = new User("Jerry", 12); when(userRepository.insert(any(User.class))).then(new Answer() { @@ -53,7 +58,9 @@ public class UserServiceUnitTest { return user; } }); - + + userService = new DefaultUserService(userRepository, settingRepository, mailClient); + // When User insertedUser = userService.register(user); From 184d60ca6e8f489603c33ac38930f748522a99da Mon Sep 17 00:00:00 2001 From: Juan Moreno Date: Fri, 2 Nov 2018 10:36:21 -0300 Subject: [PATCH 4/5] Hibernate Field Naming with Spring Boot Issue: BAEL-2098 --- .../com/baeldung/naming/HibernateConfig.java | 19 ++++++ .../naming/MetadataExtractorIntegrator.java | 41 +++++++++++++ .../com/baeldung/naming/entity/Account.java | 19 ++++++ .../baeldung/naming/entity/Preference.java | 16 +++++ .../LegacyJpaImplNamingIntegrationTest.java | 58 +++++++++++++++++++ .../com/baeldung/naming/NamingConfig.java | 15 +++++ ...pringBootDefaultNamingIntegrationTest.java | 54 +++++++++++++++++ .../StrategyLegacyHbmImplIntegrationTest.java | 58 +++++++++++++++++++ 8 files changed, 280 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/HibernateConfig.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/MetadataExtractorIntegrator.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Account.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Preference.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/LegacyJpaImplNamingIntegrationTest.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/NamingConfig.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/SpringBootDefaultNamingIntegrationTest.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/StrategyLegacyHbmImplIntegrationTest.java diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/HibernateConfig.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/HibernateConfig.java new file mode 100644 index 0000000000..897e34d406 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/HibernateConfig.java @@ -0,0 +1,19 @@ +package com.baeldung.naming; + +import org.hibernate.jpa.boot.spi.IntegratorProvider; +import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; + +import java.util.Collections; +import java.util.Map; + +/** + * Custom implementation of the {@link HibernatePropertiesCustomizer HibernatePropertiesCustomizer}. + * We can use it to set custom hibernate properties. + */ +public class HibernateConfig implements HibernatePropertiesCustomizer { + + @Override + public void customize(Map hibernateProperties) { + hibernateProperties.put("hibernate.integrator_provider", (IntegratorProvider) () -> Collections.singletonList(MetadataExtractorIntegrator.INSTANCE)); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/MetadataExtractorIntegrator.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/MetadataExtractorIntegrator.java new file mode 100644 index 0000000000..24b5cdea64 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/MetadataExtractorIntegrator.java @@ -0,0 +1,41 @@ +package com.baeldung.naming; + +import org.hibernate.boot.Metadata; +import org.hibernate.boot.model.relational.Database; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; + +/** + * Custom implementation of the {@link Integrator Integrator} interface. + * We can use it to getting access to the binding metadata between entity mappings and database tables. + */ +public class MetadataExtractorIntegrator implements Integrator { + + public static final MetadataExtractorIntegrator INSTANCE = new MetadataExtractorIntegrator(); + + private Database database; + + private Metadata metadata; + + public Database getDatabase() { + return database; + } + + public Metadata getMetadata() { + return metadata; + } + + @Override + public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + + this.database = metadata.getDatabase(); + this.metadata = metadata; + + } + + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Account.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Account.java new file mode 100644 index 0000000000..6145818c5b --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Account.java @@ -0,0 +1,19 @@ +package com.baeldung.naming.entity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.List; + +@Entity +public class Account { + + @Id private Long id; + + private String defaultEmail; + + @OneToMany List preferences; + + @Column(name = "\"Secondary_Email\"") private String secondaryEmail; +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Preference.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Preference.java new file mode 100644 index 0000000000..928884a2c5 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Preference.java @@ -0,0 +1,16 @@ +package com.baeldung.naming.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class Preference { + + @Id private Long id; + + private String name; + + @ManyToOne private Account account; + +} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/LegacyJpaImplNamingIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/LegacyJpaImplNamingIntegrationTest.java new file mode 100644 index 0000000000..e68be3bed8 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/LegacyJpaImplNamingIntegrationTest.java @@ -0,0 +1,58 @@ +package com.baeldung.naming; + +import com.baeldung.naming.entity.Account; +import org.assertj.core.api.SoftAssertions; +import org.hibernate.boot.Metadata; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Table; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@DataJpaTest +@TestPropertySource(properties = { + "spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl", + "spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl" +}) +public class LegacyJpaImplNamingIntegrationTest extends NamingConfig { + + @Test + public void givenLegacyJpaImplNamingStrategy_whenCreateDatabase_thenGetStrategyNames() { + Metadata metadata = MetadataExtractorIntegrator.INSTANCE.getMetadata(); + String entity = Account.class.getCanonicalName(); + PersistentClass persistentClass = metadata.getEntityBinding(entity); + Table table = persistentClass.getTable(); + String physicalNameExpected = "Secondary_Email"; + String implicitNameExpected = "defaultEmail"; + String tableNameExpected = "Account"; + + String tableNameCreated = table.getName(); + boolean columnNameIsQuoted = table + .getColumn(3) + .isQuoted(); + String physicalNameCreated = table + .getColumn(3) + .getName(); + String implicitNameCreated = table + .getColumn(2) + .getName(); + + SoftAssertions.assertSoftly(softly -> { + softly + .assertThat(columnNameIsQuoted) + .isTrue(); + softly + .assertThat(tableNameCreated) + .isEqualTo(tableNameExpected); + softly + .assertThat(physicalNameCreated) + .isEqualTo(physicalNameExpected); + softly + .assertThat(implicitNameCreated) + .isEqualTo(implicitNameExpected); + }); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/NamingConfig.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/NamingConfig.java new file mode 100644 index 0000000000..c3ef37aeb4 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/NamingConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.naming; + +import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +public class NamingConfig { + @TestConfiguration + static class Config { + @Bean + public HibernatePropertiesCustomizer customizer() { + return new HibernateConfig(); + } + } +} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/SpringBootDefaultNamingIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/SpringBootDefaultNamingIntegrationTest.java new file mode 100644 index 0000000000..089430aabb --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/SpringBootDefaultNamingIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.naming; + +import com.baeldung.naming.entity.Account; +import org.assertj.core.api.SoftAssertions; +import org.hibernate.boot.Metadata; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Table; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@DataJpaTest +@TestPropertySource(properties = { + "spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy", + "spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy" +}) +public class SpringBootDefaultNamingIntegrationTest extends NamingConfig { + + @Test + public void givenDefaultBootNamingStrategy_whenCreateDatabase_thenGetStrategyNames() { + Metadata metadata = MetadataExtractorIntegrator.INSTANCE.getMetadata(); + String entity = Account.class.getCanonicalName(); + PersistentClass persistentClass = metadata.getEntityBinding(entity); + Table table = persistentClass.getTable(); + String physicalNameExpected = "secondary_email"; + String implicitNameExpected = "default_email"; + String tableNameExpected = "account"; + + String tableNameCreated = table.getName(); + String physicalNameCreated = table + .getColumn(3) + .getName(); + String implicitNameCreated = table + .getColumn(2) + .getName(); + + SoftAssertions softly = new SoftAssertions(); + softly + .assertThat(tableNameCreated) + .isEqualTo(tableNameExpected); + softly + .assertThat(physicalNameCreated) + .isEqualTo(physicalNameExpected); + softly + .assertThat(implicitNameCreated) + .isEqualTo(implicitNameExpected); + softly.assertAll(); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/StrategyLegacyHbmImplIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/StrategyLegacyHbmImplIntegrationTest.java new file mode 100644 index 0000000000..046755d9bc --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/StrategyLegacyHbmImplIntegrationTest.java @@ -0,0 +1,58 @@ +package com.baeldung.naming; + +import com.baeldung.naming.entity.Preference; +import org.assertj.core.api.SoftAssertions; +import org.hibernate.boot.Metadata; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Table; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Collection; + +@RunWith(SpringRunner.class) +@DataJpaTest +@TestPropertySource(properties = { + "spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl", + "spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl", +}) +public class StrategyLegacyHbmImplIntegrationTest extends NamingConfig { + + @Test + public void givenLegacyHbmImplNamingNamingStrategy_whenCreateDatabase_thenGetStrategyNames() { + Metadata metadata = MetadataExtractorIntegrator.INSTANCE.getMetadata(); + String entity = Preference.class.getCanonicalName(); + PersistentClass persistentClass = metadata.getEntityBinding(entity); + Collection tables = metadata + .getDatabase() + .getDefaultNamespace() + .getTables(); + Table preferenceTable = persistentClass.getTable(); + String tableNameExpected = "Account_preferences"; + Table accountPreferencesTable = tables + .stream() + .filter(table -> table + .getName() + .equals(tableNameExpected)) + .findFirst() + .get(); + String implicitNameExpected = "account"; + + String implicitNameCreated = preferenceTable + .getColumn(3) + .getName(); + String tableNameCreated = accountPreferencesTable.getName(); + + SoftAssertions.assertSoftly(softly -> { + softly + .assertThat(implicitNameCreated) + .isEqualTo(implicitNameExpected); + softly + .assertThat(tableNameCreated) + .isEqualTo(tableNameExpected); + }); + } +} From 947e8a3edc680f70358fad8aec1b9f7dde127a22 Mon Sep 17 00:00:00 2001 From: bungrudi <30967151+bungrudi@users.noreply.github.com> Date: Fri, 2 Nov 2018 22:14:27 +0700 Subject: [PATCH 5/5] Guide to EnumMap Issue: BAEL-2260 --- core-java-collections/pom.xml | 2 +- .../java/com/baeldung/enummap/DummyEnum.java | 13 ++ .../enummap/EnumMapBenchmarkLiveTest.java | 119 +++++++++++++++ .../com/baeldung/enummap/EnumMapUnitTest.java | 144 ++++++++++++++++++ 4 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java create mode 100644 core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java create mode 100644 core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java diff --git a/core-java-collections/pom.xml b/core-java-collections/pom.xml index 39ddc17684..d3ef953e01 100644 --- a/core-java-collections/pom.xml +++ b/core-java-collections/pom.xml @@ -65,7 +65,7 @@ 4.14.011.7.0 - 3.6.1 + 3.11.17.1.0 diff --git a/core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java b/core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java new file mode 100644 index 0000000000..906c820fa3 --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java @@ -0,0 +1,13 @@ +package com.baeldung.enummap; + +/** + * This enum is used for benchmarking, therefore has many values. + */ +public enum DummyEnum { + CCC_000, + CCC_001,CCC_002,CCC_003,CCC_004,CCC_005,CCC_006,CCC_007,CCC_008,CCC_009,CCC_010, + CCC_011,CCC_012,CCC_013,CCC_014,CCC_015,CCC_016,CCC_017,CCC_018,CCC_019,CCC_020, + CCC_021,CCC_022,CCC_023,CCC_024,CCC_025,CCC_026,CCC_027,CCC_028,CCC_029,CCC_030, + CCC_031,CCC_032,CCC_033,CCC_034,CCC_035,CCC_036,CCC_037,CCC_038,CCC_039,CCC_040, + CCC_041,CCC_042,CCC_043,CCC_044,CCC_045,CCC_046,CCC_047,CCC_048,CCC_049, +} diff --git a/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java b/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java new file mode 100644 index 0000000000..997a8ba65b --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java @@ -0,0 +1,119 @@ +package com.baeldung.enummap; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode({ Mode.AverageTime }) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +public class EnumMapBenchmarkLiveTest { + + @State(Scope.Thread) + public static class BenchmarkState { + EnumMap enumMap = new EnumMap<>(DummyEnum.class); + HashMap hashMap = new HashMap<>(); + TreeMap treeMap = new TreeMap<>(); + int len = DummyEnum.values().length; + Random random = new Random(); + int randomIndex; + + @Setup(Level.Trial) + public void setUp() { + DummyEnum[] values = DummyEnum.values(); + for (int i = 0; i < len; i++) { + enumMap.put(values[i], values[i].toString()); + hashMap.put(values[i], values[i].toString()); + treeMap.put(values[i], values[i].toString()); + } + } + + @Setup(Level.Invocation) + public void additionalSetup() { + randomIndex = random.nextInt(len); + } + + } + + @Benchmark + public int benchmark01_EnumMapPut(BenchmarkState s) { + s.enumMap.put(DummyEnum.values()[s.randomIndex], DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark01_HashMapPut(BenchmarkState s) { + s.hashMap.put(DummyEnum.values()[s.randomIndex], DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark01_TreeMapPut(BenchmarkState s) { + s.treeMap.put(DummyEnum.values()[s.randomIndex], DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark02_EnumMapGet(BenchmarkState s) { + s.enumMap.get(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark02_HashMapGet(BenchmarkState s) { + s.hashMap.get(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark02_TreeMapGet(BenchmarkState s) { + s.treeMap.get(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark03_EnumMapContainsKey(BenchmarkState s) { + s.enumMap.containsKey(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark03_HashMapContainsKey(BenchmarkState s) { + s.hashMap.containsKey(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark03_TreeMapContainsKey(BenchmarkState s) { + s.treeMap.containsKey(DummyEnum.values()[s.randomIndex]); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark04_EnumMapContainsValue(BenchmarkState s) { + s.enumMap.containsValue(DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark04_HashMapContainsValue(BenchmarkState s) { + s.hashMap.containsValue(DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + @Benchmark + public int benchmark04_TreeMapContainsValue(BenchmarkState s) { + s.treeMap.containsValue(DummyEnum.values()[s.randomIndex].toString()); + return ++s.randomIndex; + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder().include(EnumMapBenchmarkLiveTest.class.getSimpleName()).threads(1).forks(0).shouldFailOnError(true).shouldDoGC(false).jvmArgs("-server").build(); + new Runner(options).run(); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java b/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java new file mode 100644 index 0000000000..d9d6cf2c39 --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java @@ -0,0 +1,144 @@ +package com.baeldung.enummap; + +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +import static java.util.AbstractMap.SimpleEntry; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +public class EnumMapUnitTest { + public enum DayOfWeek { + MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY + } + + @Test + public void whenContructedWithEnumType_ThenOnlyAcceptThatAsKey() { + Map dayMap = new EnumMap<>(DayOfWeek.class); + assertThatCode( + () -> dayMap.put(TimeUnit.NANOSECONDS, "NANOSECONDS")) + .isInstanceOf(ClassCastException.class); + } + + @Test + public void whenConstructedWithEnumMap_ThenSameKeyTypeAndInitialMappings() { + EnumMap activityMap = new EnumMap<>(DayOfWeek.class); + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + activityMap.put(DayOfWeek.TUESDAY, "Basketball"); + + EnumMap activityMapCopy = new EnumMap<>(activityMap); + assertThat(activityMapCopy.size()).isEqualTo(2); + assertThat(activityMapCopy.get(DayOfWeek.MONDAY)) + .isEqualTo("Soccer"); + assertThat(activityMapCopy.get(DayOfWeek.TUESDAY)) + .isEqualTo("Basketball"); + } + + @Test + public void givenEmptyMap_whenConstructedWithMap_ThenException() { + HashMap ordinaryMap = new HashMap(); + assertThatCode(() -> new EnumMap(ordinaryMap)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Specified map is empty"); + } + + @Test + public void givenMapWithEntries_whenConstructedWithMap_ThenSucceed() { + HashMap ordinaryMap = new HashMap<>(); + ordinaryMap.put(DayOfWeek.MONDAY, "Soccer"); + ordinaryMap.put(DayOfWeek.TUESDAY, "Basketball"); + EnumMap enumMap = new EnumMap<>(ordinaryMap); + assertThat(enumMap.size()).isEqualTo(2); + assertThat(enumMap.get(DayOfWeek.MONDAY)).isEqualTo("Soccer"); + assertThat(enumMap.get(DayOfWeek.TUESDAY)).isEqualTo("Basketball"); + } + + @Test + public void givenMapWithMultiTypeEntries_whenConstructedWithMap_ThenException() { + HashMap ordinaryMap = new HashMap<>(); + ordinaryMap.put(DayOfWeek.MONDAY, "Soccer"); + ordinaryMap.put(TimeUnit.MILLISECONDS, "Other enum type"); + assertThatCode(() -> new EnumMap(ordinaryMap)) + .isInstanceOf(ClassCastException.class); + } + + @Test + public void whenPut_thenGet() { + Map activityMap = new EnumMap(DayOfWeek.class); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + activityMap.put(DayOfWeek.THURSDAY, null); + assertThat(activityMap.get(DayOfWeek.WEDNESDAY)).isEqualTo("Hiking"); + assertThat(activityMap.get(DayOfWeek.THURSDAY)).isNull(); + } + + @Test + public void givenMapping_whenContains_thenTrue() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isFalse(); + assertThat(activityMap.containsValue("Hiking")).isFalse(); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isTrue(); + assertThat(activityMap.containsValue("Hiking")).isTrue(); + + assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isFalse(); + assertThat(activityMap.containsValue(null)).isFalse(); + activityMap.put(DayOfWeek.SATURDAY, null); + assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isTrue(); + assertThat(activityMap.containsValue(null)).isTrue(); + } + + @Test + public void whenRemove_thenRemoved() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + assertThat(activityMap.remove(DayOfWeek.MONDAY)).isEqualTo("Soccer"); + assertThat(activityMap.containsKey(DayOfWeek.MONDAY)).isFalse(); + + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + assertThat(activityMap.remove(DayOfWeek.MONDAY, "Hiking")).isEqualTo(false); + assertThat(activityMap.remove(DayOfWeek.MONDAY, "Soccer")).isEqualTo(true); + } + + @Test + public void whenSubView_thenSubViewOrdered() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + activityMap.put(DayOfWeek.THURSDAY, "Karate"); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + + Collection values = activityMap.values(); + assertThat(values).containsExactly("Soccer", "Hiking", "Karate"); + + Set keys = activityMap.keySet(); + assertThat(keys) + .containsExactly(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY,DayOfWeek.THURSDAY); + + assertThat(activityMap.entrySet()) + .containsExactly( + new SimpleEntry(DayOfWeek.MONDAY, "Soccer"), + new SimpleEntry(DayOfWeek.WEDNESDAY, "Hiking"), + new SimpleEntry(DayOfWeek.THURSDAY, "Karate")); + } + + @Test + public void givenSubView_whenChange_thenReflected() { + EnumMap activityMap = new EnumMap(DayOfWeek.class); + activityMap.put(DayOfWeek.THURSDAY, "Karate"); + activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); + activityMap.put(DayOfWeek.MONDAY, "Soccer"); + + Collection values = activityMap.values(); + assertThat(values).containsExactly("Soccer", "Hiking", "Karate"); + + activityMap.put(DayOfWeek.TUESDAY, "Basketball"); + assertThat(values) + .containsExactly("Soccer", "Basketball", "Hiking", "Karate"); + + values.remove("Hiking"); + assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isFalse(); + assertThat(activityMap.size()).isEqualTo(3); + } +}