Skip to content

Commit 9b5cb78

Browse files
committed
Merge branch 'gh205_county_url'
Fix #205
2 parents da08d63 + f5d0463 commit 9b5cb78

23 files changed

+106
-93
lines changed

Diff for: src/main/java/ru/mystamps/web/Url.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,10 @@ public final class Url {
6262
public static final String LIST_CATEGORIES_PAGE = "/category/list";
6363

6464
public static final String ADD_COUNTRY_PAGE = "/country/add";
65-
public static final String INFO_COUNTRY_PAGE = "/country/{id}/{slug}";
6665
public static final String LIST_COUNTRIES_PAGE = "/country/list";
66+
public static final String INFO_COUNTRY_PAGE = "/country/{slug}";
67+
// For backward compatibility
68+
public static final String INFO_COUNTRY_BY_ID_PAGE = "/country/{id}/{slug}";
6769

6870
public static final String INFO_COLLECTION_PAGE = "/collection/{id}/{slug}";
6971

Diff for: src/main/java/ru/mystamps/web/controller/CountryController.java

+27-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import javax.validation.Valid;
2525

2626
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
27+
import org.springframework.http.HttpStatus;
2728
import org.springframework.stereotype.Controller;
2829
import org.springframework.ui.Model;
2930
import org.springframework.validation.BindingResult;
@@ -32,7 +33,9 @@
3233
import org.springframework.web.bind.annotation.PathVariable;
3334
import org.springframework.web.bind.annotation.RequestMapping;
3435
import org.springframework.web.bind.annotation.RequestMethod;
36+
import org.springframework.web.servlet.View;
3537
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
38+
import org.springframework.web.servlet.view.RedirectView;
3639
import org.springframework.web.util.UriComponentsBuilder;
3740

3841
import lombok.RequiredArgsConstructor;
@@ -80,7 +83,7 @@ public String processInput(
8083
UrlEntityDto countryUrl = countryService.add(form, currentUserId);
8184

8285
String dstUrl = UriComponentsBuilder.fromUriString(Url.INFO_COUNTRY_PAGE)
83-
.buildAndExpand(countryUrl.getId(), countryUrl.getSlug())
86+
.buildAndExpand(countryUrl.getSlug())
8487
.toString();
8588

8689
redirectAttributes.addFlashAttribute("justAddedCountry", true);
@@ -89,8 +92,8 @@ public String processInput(
8992
}
9093

9194
@RequestMapping(Url.INFO_COUNTRY_PAGE)
92-
public String showInfo(
93-
@Country @PathVariable("id") LinkEntityDto country,
95+
public String showInfoBySlug(
96+
@Country @PathVariable("slug") LinkEntityDto country,
9497
Model model,
9598
Locale userLocale,
9699
HttpServletResponse response)
@@ -112,6 +115,27 @@ public String showInfo(
112115
return "country/info";
113116
}
114117

118+
/**
119+
* @author Aleksander Parkhomenko
120+
*/
121+
@RequestMapping(Url.INFO_COUNTRY_BY_ID_PAGE)
122+
public View showInfoById(
123+
@Country @PathVariable("slug") LinkEntityDto country,
124+
HttpServletResponse response)
125+
throws IOException {
126+
127+
if (country == null) {
128+
response.sendError(HttpServletResponse.SC_NOT_FOUND);
129+
return null;
130+
}
131+
132+
RedirectView view = new RedirectView();
133+
view.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
134+
view.setUrl(Url.INFO_COUNTRY_PAGE);
135+
136+
return view;
137+
}
138+
115139
@RequestMapping(Url.LIST_COUNTRIES_PAGE)
116140
public void list(Model model, Locale userLocale) {
117141
String lang = LocaleUtils.getLanguageOrNull(userLocale);

Diff for: src/main/java/ru/mystamps/web/controller/SeriesController.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ public Iterable<SelectEntityDto> getCategories(Locale userLocale) {
113113
}
114114

115115
@ModelAttribute("countries")
116-
public Iterable<SelectEntityDto> getCountries(Locale userLocale) {
116+
public Iterable<LinkEntityDto> getCountries(Locale userLocale) {
117117
String lang = LocaleUtils.getLanguageOrNull(userLocale);
118-
return countryService.findAllAsSelectEntities(lang);
118+
return countryService.findAllAsLinkEntities(lang);
119119
}
120120

121121
@RequestMapping(Url.ADD_SERIES_PAGE)

Diff for: src/main/java/ru/mystamps/web/controller/converter/LinkEntityDtoGenericConverter.java

+5-6
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,22 @@ public Object convert(Object value, TypeDescriptor sourceType, TypeDescriptor ta
6868
return null;
6969
}
7070

71+
String lang = LocaleUtils.getCurrentLanguageOrNull();
72+
if (hasCountryAnnotation(targetType)) {
73+
return countryService.findOneAsLinkEntity(string, lang);
74+
}
75+
7176
try {
7277
Integer id = Integer.valueOf(string);
7378
if (id <= 0) {
7479
LOG.warn("Attempt to convert non positive number ({})", id);
7580
return null;
7681
}
7782

78-
String lang = LocaleUtils.getCurrentLanguageOrNull();
79-
8083
if (hasCategoryAnnotation(targetType)) {
8184
return categoryService.findOneAsLinkEntity(id, lang);
8285
}
8386

84-
if (hasCountryAnnotation(targetType)) {
85-
return countryService.findOneAsLinkEntity(id, lang);
86-
}
87-
8887
LOG.warn(
8988
"Can't convert type '{}' because it doesn't contain supported annotations",
9089
targetType

Diff for: src/main/java/ru/mystamps/web/dao/JdbcCountryDao.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ public interface JdbcCountryDao {
3232
List<Object[]> getStatisticsOf(Integer collectionId, String lang);
3333
Iterable<SelectEntityDto> findAllAsSelectEntities(String lang);
3434
Iterable<LinkEntityDto> findAllAsLinkEntities(String lang);
35-
LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang);
35+
LinkEntityDto findOneAsLinkEntity(String slug, String lang);
3636
}

Diff for: src/main/java/ru/mystamps/web/dao/impl/JdbcCountryDaoImpl.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public class JdbcCountryDaoImpl implements JdbcCountryDao {
6868
@Value("${country.find_all_countries_names_with_slug}")
6969
private String findCountriesNamesWithSlugSql;
7070

71-
@Value("${country.find_country_link_info_by_id}")
72-
private String findCountryLinkEntityByIdSql;
71+
@Value("${country.find_country_link_info_by_slug}")
72+
private String findCountryLinkEntityBySlugSql;
7373

7474
@Override
7575
public Integer add(AddCountryDbDto country) {
@@ -167,14 +167,14 @@ public Iterable<LinkEntityDto> findAllAsLinkEntities(String lang) {
167167
}
168168

169169
@Override
170-
public LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang) {
170+
public LinkEntityDto findOneAsLinkEntity(String slug, String lang) {
171171
Map<String, Object> params = new HashMap<>();
172-
params.put("country_id", countryId);
172+
params.put("slug", slug);
173173
params.put("lang", lang);
174174

175175
try {
176176
return jdbcTemplate.queryForObject(
177-
findCountryLinkEntityByIdSql,
177+
findCountryLinkEntityBySlugSql,
178178
params,
179179
RowMappers::forLinkEntityDto
180180
);

Diff for: src/main/java/ru/mystamps/web/entity/Country.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class Country {
4848
@Column(name = "name_ru", length = NAME_LENGTH, nullable = false, unique = true)
4949
private String nameRu;
5050

51-
@Column(length = SLUG_LENGTH, nullable = false)
51+
@Column(length = SLUG_LENGTH, unique = true, nullable = false)
5252
private String slug;
5353

5454
@Embedded

Diff for: src/main/java/ru/mystamps/web/service/CountryService.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@
2121

2222
import ru.mystamps.web.service.dto.AddCountryDto;
2323
import ru.mystamps.web.service.dto.LinkEntityDto;
24-
import ru.mystamps.web.service.dto.SelectEntityDto;
2524
import ru.mystamps.web.service.dto.UrlEntityDto;
2625

2726
public interface CountryService {
2827
UrlEntityDto add(AddCountryDto dto, Integer userId);
29-
Iterable<SelectEntityDto> findAllAsSelectEntities(String lang);
3028
Iterable<LinkEntityDto> findAllAsLinkEntities(String lang);
31-
LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang);
29+
LinkEntityDto findOneAsLinkEntity(String slug, String lang);
3230
long countAll();
3331
long countCountriesOf(Integer collectionId);
3432
long countByName(String name);

Diff for: src/main/java/ru/mystamps/web/service/CountryServiceImpl.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import ru.mystamps.web.dao.dto.AddCountryDbDto;
3737
import ru.mystamps.web.service.dto.AddCountryDto;
3838
import ru.mystamps.web.service.dto.LinkEntityDto;
39-
import ru.mystamps.web.service.dto.SelectEntityDto;
4039
import ru.mystamps.web.service.dto.UrlEntityDto;
4140
import ru.mystamps.web.util.SlugUtils;
4241

@@ -80,12 +79,6 @@ public UrlEntityDto add(AddCountryDto dto, Integer userId) {
8079
return new UrlEntityDto(id, slug);
8180
}
8281

83-
@Override
84-
@Transactional(readOnly = true)
85-
public Iterable<SelectEntityDto> findAllAsSelectEntities(String lang) {
86-
return countryDao.findAllAsSelectEntities(lang);
87-
}
88-
8982
@Override
9083
@Transactional(readOnly = true)
9184
public Iterable<LinkEntityDto> findAllAsLinkEntities(String lang) {
@@ -94,10 +87,11 @@ public Iterable<LinkEntityDto> findAllAsLinkEntities(String lang) {
9487

9588
@Override
9689
@Transactional(readOnly = true)
97-
public LinkEntityDto findOneAsLinkEntity(Integer countryId, String lang) {
98-
Validate.isTrue(countryId != null, "Country id must be non null");
90+
public LinkEntityDto findOneAsLinkEntity(String slug, String lang) {
91+
Validate.isTrue(slug != null, "Country slug must be non null");
92+
Validate.isTrue(!slug.trim().isEmpty(), "Country slug must be non empty");
9993

100-
return countryDao.findOneAsLinkEntity(countryId, lang);
94+
return countryDao.findOneAsLinkEntity(slug, lang);
10195
}
10296

10397
@Override

Diff for: src/main/resources/liquibase/version/0.4.xml

+1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
<include file="0.4/2016-01-02--non_unique_catalog_numbers.xml" relativeToChangelogFile="true" />
1414
<include file="0.4/2016-01-04--unique_series_in_collection.xml" relativeToChangelogFile="true" />
1515
<include file="0.4/2016-02-19--csrf_events.xml" relativeToChangelogFile="true" />
16+
<include file="0.4/2016-01-14--unique_slug_in_countries.xml" relativeToChangelogFile="true" />
1617

1718
</databaseChangeLog>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<databaseChangeLog
3+
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
6+
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
7+
8+
<changeSet id="add-unique-constraint-to-slug-in-countries-table" author="AleksSPb" context="scheme">
9+
10+
<preConditions>
11+
<sqlCheck expectedResult="0">
12+
SELECT COUNT(*) as num
13+
FROM countries
14+
GROUP BY slug
15+
HAVING num > 1
16+
UNION SELECT 0
17+
</sqlCheck>
18+
</preConditions>
19+
20+
<addUniqueConstraint
21+
tableName="countries"
22+
columnNames="slug"
23+
constraintName="uc_countries_slug"/>
24+
25+
</changeSet>
26+
27+
</databaseChangeLog>

Diff for: src/main/resources/sql/country_dao_queries.properties

+4-4
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ country.find_all_countries_names_with_slug = \
6464
FROM countries c \
6565
ORDER BY CASE WHEN 'ru' = :lang THEN c.name_ru ELSE c.name END
6666

67-
country.find_country_link_info_by_id = \
68-
SELECT CASE WHEN 'ru' = :lang THEN c.name_ru ELSE c.name END AS name \
67+
country.find_country_link_info_by_slug = \
68+
SELECT CASE WHEN 'ru' = :lang THEN c.name_ru ELSE c.name END AS name \
6969
, c.slug \
7070
, c.id \
71-
FROM countries c \
72-
WHERE c.id = :country_id \
71+
FROM countries c \
72+
WHERE c.slug = :slug \
7373
ORDER BY CASE WHEN 'ru' = :lang THEN c.name_ru ELSE c.name END

Diff for: src/main/webapp/WEB-INF/views/category/info.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ <h3 th:text="${categoryName}">
105105
<ul th:if="${not #lists.isEmpty(seriesOfCategory)}" th:remove="all-but-first">
106106
<li th:each="series: ${seriesOfCategory}">
107107
<span th:if="${series.country.id != null}" th:remove="tag">
108-
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(id=${series.country.id},slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
108+
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
109109
</span>
110110

111111
<a href="../series/info.html" th:href="@{${INFO_SERIES_PAGE}(id=${series.id})}">

Diff for: src/main/webapp/WEB-INF/views/collection/info.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ <h3 class="text-center" th:text="#{t_collection_of(${ownerName})}">
123123
</span>
124124

125125
<span th:if="${series.country.id != null}" th:remove="tag">
126-
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(id=${series.country.id},slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
126+
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
127127
</span>
128128

129129
<a href="../series/info.html" th:href="@{${INFO_SERIES_PAGE}(id=${series.id})}">

Diff for: src/main/webapp/WEB-INF/views/country/info.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<link rel="stylesheet" href="https://cdn.rawgit.com/usrz/bootstrap-languages/3ac2a3d2b27ac43a471cd99e79d378a03b2c6b5f/languages.min.css" th:href="${BOOTSTRAP_LANGUAGE}" />
1414
<link rel="stylesheet" href="../../static/styles/main.min.css" th:href="${MAIN_CSS}" />
1515
<!--/*/
16-
<link rel="canonical" th:href="@{${PUBLIC_URL} + ${INFO_COUNTRY_PAGE}(id=${countryId},slug=${countrySlug})}" />
16+
<link rel="canonical" th:href="@{${PUBLIC_URL} + ${INFO_COUNTRY_PAGE}(slug=${countrySlug})}" />
1717
/*/-->
1818
</head>
1919
<body>

Diff for: src/main/webapp/WEB-INF/views/country/list.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ <h3 th:text="${#strings.capitalize(country_list)}">
9292

9393
<ul th:if="${not #lists.isEmpty(countries)}">
9494
<li th:each="country : ${countries}">
95-
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(id=${country.id},slug=${country.slug})}" th:text="${country.name}">Italy</a>
95+
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(slug=${country.slug})}" th:text="${country.name}">Italy</a>
9696
</li>
9797
</ul>
9898
</div>

Diff for: src/main/webapp/WEB-INF/views/series/add.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,12 @@ <h3 th:text="${#strings.capitalize(add_series)}">
153153
<select id="country" class="form-control" th:field="*{country}">
154154
<option value="" th:text="#{t_not_chosen}">Not chosen</option>
155155
<!--/*/
156-
<option th:each="country : ${countries}" th:value="${country.id}" th:text="${country.name}"></option>
156+
<option th:each="country : ${countries}" th:value="${country.slug}" th:text="${country.name}"></option>
157157
/*/-->
158158
<!--/*-->
159-
<option value="1">Russia</option>
160-
<option value="2">Canada</option>
161-
<option value="3">Italy</option>
159+
<option value="russia">Russia</option>
160+
<option value="canada">Canada</option>
161+
<option value="italy">Italy</option>
162162
<!--*/-->
163163
</select>
164164
<small sec:authorize="hasAuthority('CREATE_COUNTRY')">

Diff for: src/main/webapp/WEB-INF/views/series/info.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@
126126
</dt>
127127
<dd id="country_name">
128128
<a href="../country/info.html"
129-
th:href="@{${INFO_COUNTRY_PAGE}(id=${series.country.id},slug=${series.country.slug})}"
129+
th:href="@{${INFO_COUNTRY_PAGE}(slug=${series.country.slug})}"
130130
th:text="${series.country.name}">
131131
Italy
132132
</a>

Diff for: src/main/webapp/WEB-INF/views/series/search_result.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ <h3 class="text-center" th:text="${#strings.capitalize(search_results)}">
105105
<a href="../category/info.html" th:href="@{${INFO_CATEGORY_PAGE}(id=${series.category.id},slug=${series.category.slug})}" th:text="${series.category.name}">Animals</a>&nbsp;&raquo;
106106
</span>
107107
<span th:if="${series.country.id != null}" th:remove="tag">
108-
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(id=${series.country.id},slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
108+
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
109109
</span>
110110
<a href="../series/info.html" th:href="@{${INFO_SERIES_PAGE}(id=${series.id})}">
111111
<span th:remove="tag" th:if="${series.releaseYear != null}" th:text="|${series.releaseYear}, |">1999, </span>

Diff for: src/main/webapp/WEB-INF/views/site/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ <h4 class="panel-title" th:text="#{t_recently_added_series}">Recently added seri
153153
</span>
154154

155155
<span th:if="${series.country.id != null}" th:remove="tag">
156-
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(id=${series.country.id},slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
156+
<a href="../country/info.html" th:href="@{${INFO_COUNTRY_PAGE}(slug=${series.country.slug})}" th:text="${series.country.name}">Italy</a>&nbsp;&raquo;
157157
</span>
158158

159159
<a href="../series/info.html" th:href="@{${INFO_SERIES_PAGE}(id=${series.id})}">

0 commit comments

Comments
 (0)