Skip to content

Commit 474843d

Browse files
committed
CountryController.showInfo(): replace Country by LinkEntityDto.
See also: http://docs.spring.io/spring/docs/4.2.1.RELEASE/spring-framework-reference/html/validation.html#core-convert-GenericConverter-SPI Addressed to #120 No functional changes.
1 parent d1e181d commit 474843d

File tree

10 files changed

+151
-15
lines changed

10 files changed

+151
-15
lines changed

src/main/java/ru/mystamps/web/config/MvcConfig.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
4242
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
4343

44-
import ru.mystamps.web.controller.converter.LinkEntityDtoConverter;
44+
import ru.mystamps.web.controller.converter.LinkEntityDtoGenericConverter;
4545
import ru.mystamps.web.support.spring.security.CustomUserDetailsArgumentResolver;
4646
import ru.mystamps.web.Url;
4747
import ru.mystamps.web.support.spring.security.UserArgumentResolver;
@@ -56,7 +56,12 @@ public class MvcConfig extends WebMvcConfigurerAdapter {
5656

5757
@Override
5858
public void addFormatters(FormatterRegistry registry) {
59-
registry.addConverter(new LinkEntityDtoConverter(servicesConfig.getCategoryService()));
59+
registry.addConverter(
60+
new LinkEntityDtoGenericConverter(
61+
servicesConfig.getCategoryService(),
62+
servicesConfig.getCountryService()
63+
)
64+
);
6065
}
6166

6267
@Override

src/main/java/ru/mystamps/web/controller/CountryController.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@
3838
import lombok.RequiredArgsConstructor;
3939

4040
import ru.mystamps.web.Url;
41-
import ru.mystamps.web.entity.Country;
4241
import ru.mystamps.web.entity.User;
4342
import ru.mystamps.web.model.AddCountryForm;
4443
import ru.mystamps.web.service.CountryService;
4544
import ru.mystamps.web.service.SeriesService;
45+
import ru.mystamps.web.service.dto.LinkEntityDto;
4646
import ru.mystamps.web.service.dto.UrlEntityDto;
47+
import ru.mystamps.web.controller.converter.annotation.Country;
4748
import ru.mystamps.web.util.LocaleUtils;
4849

4950
@Controller
@@ -89,7 +90,7 @@ public String processInput(
8990

9091
@RequestMapping(Url.INFO_COUNTRY_PAGE)
9192
public String showInfo(
92-
@PathVariable("id") Country country,
93+
@Country @PathVariable("id") LinkEntityDto country,
9394
Model model,
9495
Locale userLocale,
9596
HttpServletResponse response)
@@ -102,7 +103,7 @@ public String showInfo(
102103

103104
model.addAttribute("countryId", country.getId());
104105
model.addAttribute("countrySlug", country.getSlug());
105-
model.addAttribute("countryName", LocaleUtils.getLocalizedName(userLocale, country));
106+
model.addAttribute("countryName", country.getName());
106107

107108
String lang = LocaleUtils.getLanguageOrNull(userLocale);
108109
Integer countryId = country.getId();

src/main/java/ru/mystamps/web/controller/converter/LinkEntityDtoConverter.java renamed to src/main/java/ru/mystamps/web/controller/converter/LinkEntityDtoGenericConverter.java

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,65 @@
1717
*/
1818
package ru.mystamps.web.controller.converter;
1919

20+
import java.util.Collections;
21+
import java.util.Set;
22+
2023
import org.slf4j.Logger;
2124
import org.slf4j.LoggerFactory;
2225

2326
import org.springframework.core.convert.TypeDescriptor;
24-
import org.springframework.core.convert.converter.ConditionalConverter;
25-
import org.springframework.core.convert.converter.Converter;
27+
import org.springframework.core.convert.converter.ConditionalGenericConverter;
2628

2729
import lombok.RequiredArgsConstructor;
2830

31+
import ru.mystamps.web.controller.converter.annotation.Country;
2932
import ru.mystamps.web.service.CategoryService;
33+
import ru.mystamps.web.service.CountryService;
3034
import ru.mystamps.web.service.dto.LinkEntityDto;
3135
import ru.mystamps.web.controller.converter.annotation.Category;
3236
import ru.mystamps.web.util.LocaleUtils;
3337

3438
@RequiredArgsConstructor
35-
public class LinkEntityDtoConverter
36-
implements Converter<String, LinkEntityDto>, ConditionalConverter {
39+
public class LinkEntityDtoGenericConverter implements ConditionalGenericConverter {
3740

38-
private static final Logger LOG = LoggerFactory.getLogger(LinkEntityDtoConverter.class);
41+
private static final Logger LOG = LoggerFactory.getLogger(LinkEntityDtoGenericConverter.class);
3942

4043
private final CategoryService categoryService;
44+
private final CountryService countryService;
4145

4246
@Override
43-
public LinkEntityDto convert(String value) {
44-
String lang = LocaleUtils.getCurrentLanguageOrNull();
47+
public Set<ConvertiblePair> getConvertibleTypes() {
48+
return Collections.singleton(new ConvertiblePair(String.class, LinkEntityDto.class));
49+
}
50+
51+
@Override
52+
public Object convert(Object value, TypeDescriptor sourceType, TypeDescriptor targetType) {
53+
if (value == null) {
54+
LOG.warn("Attempt to convert null");
55+
return null;
56+
}
4557

4658
try {
47-
Integer id = Integer.valueOf(value);
59+
Integer id = Integer.valueOf(value.toString());
4860
if (id <= 0) {
4961
LOG.warn("Attempt to convert non positive number ({})", id);
5062
return null;
5163
}
5264

53-
return categoryService.findOneAsLinkEntity(id, lang);
65+
String lang = LocaleUtils.getCurrentLanguageOrNull();
66+
67+
if (targetType.hasAnnotation(Category.class)) {
68+
return categoryService.findOneAsLinkEntity(id, lang);
69+
70+
} else if (targetType.hasAnnotation(Country.class)) {
71+
return countryService.findOneAsLinkEntity(id, lang);
72+
}
73+
74+
LOG.warn(
75+
"Can't convert type '{}' because it doesn't contain supported annotations",
76+
targetType
77+
);
78+
return null;
5479

5580
} catch (NumberFormatException ex) {
5681
LOG.warn("Can't convert value '{}' from string to integer: {}", value, ex.getMessage());
@@ -65,7 +90,7 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
6590
return false;
6691
}
6792

68-
return targetType.hasAnnotation(Category.class);
93+
return targetType.hasAnnotation(Category.class) || targetType.hasAnnotation(Country.class);
6994
}
7095

7196
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (C) 2009-2015 Slava Semushin <slava.semushin@gmail.com>
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17+
*/
18+
package ru.mystamps.web.controller.converter.annotation;
19+
20+
import java.lang.annotation.Documented;
21+
import java.lang.annotation.ElementType;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
25+
26+
@Target(ElementType.PARAMETER)
27+
@Retention(RetentionPolicy.RUNTIME)
28+
@Documented
29+
public @interface Country {
30+
}

src/main/java/ru/mystamps/web/dao/JdbcCountryDao.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ public interface JdbcCountryDao {
3232
Map<String, Integer> getStatisticsOf(Integer collectionId, String lang);
3333
Iterable<SelectEntityDto> findAllAsSelectEntities(String lang);
3434
Iterable<LinkEntityDto> findAllAsLinkEntities(String lang);
35+
LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang);
3536
}

src/main/java/ru/mystamps/web/dao/impl/JdbcCountryDaoImpl.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.commons.lang3.Validate;
2626

2727
import org.springframework.beans.factory.annotation.Value;
28+
import org.springframework.dao.EmptyResultDataAccessException;
2829
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
2930
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
3031
import org.springframework.jdbc.support.GeneratedKeyHolder;
@@ -38,6 +39,7 @@
3839
import ru.mystamps.web.service.dto.SelectEntityDto;
3940

4041
@RequiredArgsConstructor
42+
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
4143
public class JdbcCountryDaoImpl implements JdbcCountryDao {
4244

4345
private final NamedParameterJdbcTemplate jdbcTemplate;
@@ -66,6 +68,9 @@ public class JdbcCountryDaoImpl implements JdbcCountryDao {
6668
@Value("${country.find_all_countries_names_with_slug}")
6769
private String findCountriesNamesWithSlugSql;
6870

71+
@Value("${country.find_country_link_info_by_id}")
72+
private String findCountryLinkEntityByIdSql;
73+
6974
@Override
7075
public Integer add(AddCountryDbDto country) {
7176
Map<String, Object> params = new HashMap<>();
@@ -169,4 +174,21 @@ public Iterable<LinkEntityDto> findAllAsLinkEntities(String lang) {
169174
);
170175
}
171176

177+
@Override
178+
public LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang) {
179+
Map<String, Object> params = new HashMap<>();
180+
params.put("country_id", countryId);
181+
params.put("lang", lang);
182+
183+
try {
184+
return jdbcTemplate.queryForObject(
185+
findCountryLinkEntityByIdSql,
186+
params,
187+
RowMappers::forLinkEntityDto
188+
);
189+
} catch (EmptyResultDataAccessException ignored) {
190+
return null;
191+
}
192+
}
193+
172194
}

src/main/java/ru/mystamps/web/service/CountryService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public interface CountryService {
2828
UrlEntityDto add(AddCountryDto dto, Integer userId);
2929
Iterable<SelectEntityDto> findAllAsSelectEntities(String lang);
3030
Iterable<LinkEntityDto> findAllAsLinkEntities(String lang);
31+
LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang);
3132
long countAll();
3233
long countCountriesOf(Integer collectionId);
3334
long countByName(String name);

src/main/java/ru/mystamps/web/service/CountryServiceImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ public Iterable<LinkEntityDto> findAllAsLinkEntities(String lang) {
9191
return countryDao.findAllAsLinkEntities(lang);
9292
}
9393

94+
@Override
95+
@Transactional(readOnly = true)
96+
public LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang) {
97+
Validate.isTrue(countryId != null, "Country id must be non null");
98+
99+
return countryDao.findOneAsLinkEntity(countryId, lang);
100+
}
101+
94102
@Override
95103
@Transactional(readOnly = true)
96104
public long countAll() {

src/main/resources/sql/country_dao_queries.properties

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,11 @@ country.find_all_countries_names_with_slug = \
6363
, c.id \
6464
FROM countries c \
6565
ORDER BY CASE WHEN 'ru' = :lang THEN c.name_ru ELSE c.name END
66+
67+
country.find_country_link_info_by_id = \
68+
SELECT CASE WHEN 'ru' = :lang THEN c.name_ru ELSE c.name END AS name \
69+
, c.slug \
70+
, c.id \
71+
FROM countries c \
72+
WHERE c.id = :country_id \
73+
ORDER BY CASE WHEN 'ru' = :lang THEN c.name_ru ELSE c.name END

src/test/groovy/ru/mystamps/web/service/CountryServiceImplTest.groovy

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,41 @@ class CountryServiceImplTest extends Specification {
259259
null | _
260260
}
261261

262+
//
263+
// Tests for findOneAsLinkEntity()
264+
//
265+
266+
def "findOneAsLinkEntity() should throw exception when country id is null"() {
267+
when:
268+
service.findOneAsLinkEntity(null, 'ru')
269+
then:
270+
thrown IllegalArgumentException
271+
}
272+
273+
def "findOneAsLinkEntity() should pass arguments to dao"() {
274+
given:
275+
Integer expectedCountryId = 15
276+
and:
277+
String expectedLang = 'fr'
278+
and:
279+
LinkEntityDto expectedDto = TestObjects.createLinkEntityDto()
280+
when:
281+
LinkEntityDto actualDto = service.findOneAsLinkEntity(expectedCountryId, expectedLang)
282+
then:
283+
1 * countryDao.findOneAsLinkEntity(
284+
{ Integer countryId ->
285+
assert expectedCountryId == countryId
286+
return true
287+
},
288+
{ String lang ->
289+
assert expectedLang == lang
290+
return true
291+
}
292+
) >> expectedDto
293+
and:
294+
actualDto == expectedDto
295+
}
296+
262297
//
263298
// Tests for countAll()
264299
//

0 commit comments

Comments
 (0)