Skip to content

Commit fcf3384

Browse files
committed
/series/{michel,scott,yvert,gibbons}/{num}: implement ability to search series by catalog number.
This change also suppress PMD warning about duplicated string literal "redirect:" in SeriesController that was introduced by dced5df commit. Fix #119
1 parent 48389d0 commit fcf3384

File tree

7 files changed

+241
-1
lines changed

7 files changed

+241
-1
lines changed

src/main/java/ru/mystamps/web/Url.java

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ public final class Url {
5151
public static final String INFO_SERIES_PAGE = "/series/{id}";
5252
public static final String ADD_IMAGE_SERIES_PAGE = "/series/{id}/image";
5353

54+
// CheckStyle: ignore WhitespaceAroundCheck for next 4 lines
55+
public static final String FIND_SERIES_BY_MICHEL = "/series/michel/{num}";
56+
public static final String FIND_SERIES_BY_SCOTT = "/series/scott/{num}";
57+
public static final String FIND_SERIES_BY_YVERT = "/series/yvert/{num}";
58+
public static final String FIND_SERIES_BY_GIBBONS= "/series/gibbons/{num}";
59+
5460
public static final String ADD_CATEGORY_PAGE = "/category/add";
5561
public static final String INFO_CATEGORY_PAGE = "/category/{id}/{slug}";
5662

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

+74
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.LinkedHashMap;
2626
import java.util.Locale;
2727
import java.util.Map;
28+
import java.util.Optional;
2829

2930
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
3031
import org.springframework.stereotype.Controller;
@@ -63,6 +64,7 @@
6364

6465
@Controller
6566
@RequiredArgsConstructor
67+
@SuppressWarnings({ "PMD.AvoidDuplicateLiterals", "PMD.TooManyMethods"})
6668
public class SeriesController {
6769

6870
private static final Integer SINCE_YEAR = 1840;
@@ -256,5 +258,77 @@ public String removeFromCollection(
256258
return "redirect:" + dstUrl;
257259
}
258260

261+
@RequestMapping(Url.FIND_SERIES_BY_MICHEL)
262+
public String findSeriesByMichel(@PathVariable("num") String michelNumberCode) {
263+
if (michelNumberCode == null) {
264+
throw new NotFoundException();
265+
}
266+
267+
Optional<Integer> seriesId = seriesService.findSeriesIdByMichelNumber(michelNumberCode);
268+
if (!seriesId.isPresent()) {
269+
throw new NotFoundException();
270+
}
271+
272+
String dstUrl = UriComponentsBuilder.fromUriString(Url.INFO_SERIES_PAGE)
273+
.buildAndExpand(seriesId.get())
274+
.toString();
275+
276+
return "redirect:" + dstUrl;
277+
}
278+
279+
@RequestMapping(Url.FIND_SERIES_BY_SCOTT)
280+
public String findSeriesByScott(@PathVariable("num") String scottNumberCode) {
281+
if (scottNumberCode == null) {
282+
throw new NotFoundException();
283+
}
284+
285+
Optional<Integer> seriesId = seriesService.findSeriesIdByScottNumber(scottNumberCode);
286+
if (!seriesId.isPresent()) {
287+
throw new NotFoundException();
288+
}
289+
290+
String dstUrl = UriComponentsBuilder.fromUriString(Url.INFO_SERIES_PAGE)
291+
.buildAndExpand(seriesId.get())
292+
.toString();
293+
294+
return "redirect:" + dstUrl;
295+
}
296+
297+
@RequestMapping(Url.FIND_SERIES_BY_YVERT)
298+
public String findSeriesByYvert(@PathVariable("num") String yvertNumberCode) {
299+
if (yvertNumberCode == null) {
300+
throw new NotFoundException();
301+
}
302+
303+
Optional<Integer> seriesId = seriesService.findSeriesIdByYvertNumber(yvertNumberCode);
304+
if (!seriesId.isPresent()) {
305+
throw new NotFoundException();
306+
}
307+
308+
String dstUrl = UriComponentsBuilder.fromUriString(Url.INFO_SERIES_PAGE)
309+
.buildAndExpand(seriesId.get())
310+
.toString();
311+
312+
return "redirect:" + dstUrl;
313+
}
314+
315+
@RequestMapping(Url.FIND_SERIES_BY_GIBBONS)
316+
public String findSeriesByGibbons(@PathVariable("num") String gibbonsNumberCode) {
317+
if (gibbonsNumberCode == null) {
318+
throw new NotFoundException();
319+
}
320+
321+
Optional<Integer> seriesId = seriesService.findSeriesIdByGibbonsNumber(gibbonsNumberCode);
322+
if (!seriesId.isPresent()) {
323+
throw new NotFoundException();
324+
}
325+
326+
String dstUrl = UriComponentsBuilder.fromUriString(Url.INFO_SERIES_PAGE)
327+
.buildAndExpand(seriesId.get())
328+
.toString();
329+
330+
return "redirect:" + dstUrl;
331+
}
332+
259333
}
260334

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

+8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818
package ru.mystamps.web.dao;
1919

20+
import java.util.Optional;
21+
2022
import ru.mystamps.web.service.dto.SeriesInfoDto;
2123
import ru.mystamps.web.service.dto.SitemapInfoDto;
2224

@@ -32,8 +34,14 @@ public interface JdbcSeriesDao {
3234
long countAllStamps();
3335
long countSeriesOfCollection(Integer collectionId);
3436
long countStampsOfCollection(Integer collectionId);
37+
3538
long countByMichelNumberCode(String michelNumber);
3639
long countByScottNumberCode(String scottNumber);
3740
long countByYvertNumberCode(String yvertNumber);
3841
long countByGibbonsNumberCode(String gibbonsNumber);
42+
43+
Optional<Integer> findSeriesIdByMichelNumberCode(String michelNumber);
44+
Optional<Integer> findSeriesIdByScottNumberCode(String scottNumber);
45+
Optional<Integer> findSeriesIdByYvertNumberCode(String yvertNumber);
46+
Optional<Integer> findSeriesIdByGibbonsNumberCode(String gibbonsNumber);
3947
}

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

+75-1
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
import java.util.Collections;
2121
import java.util.HashMap;
2222
import java.util.Map;
23+
import java.util.Optional;
2324

2425
import org.springframework.beans.factory.annotation.Value;
2526
import org.springframework.jdbc.core.RowMapper;
27+
import org.springframework.dao.EmptyResultDataAccessException;
2628
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
2729

2830
import lombok.RequiredArgsConstructor;
@@ -32,7 +34,7 @@
3234
import ru.mystamps.web.service.dto.SitemapInfoDto;
3335

3436
// TODO: move stamps related methods to separate interface (#88)
35-
@SuppressWarnings({ "PMD.AvoidDuplicateLiterals", "PMD.TooManyMethods" })
37+
@SuppressWarnings({ "PMD.AvoidDuplicateLiterals", "PMD.TooManyMethods", "PMD.TooManyFields" })
3638
@RequiredArgsConstructor
3739
public class JdbcSeriesDaoImpl implements JdbcSeriesDao {
3840

@@ -83,6 +85,18 @@ public class JdbcSeriesDaoImpl implements JdbcSeriesDao {
8385
@Value("${series.count_stamps_by_gibbons_number}")
8486
private String countStampsByGibbonsNumberSql;
8587

88+
@Value("${series.find_series_id_by_michel_number}")
89+
private String findSeriesIdByMichelNumberSql;
90+
91+
@Value("${series.find_series_id_by_scott_number}")
92+
private String findSeriesIdByScottNumberSql;
93+
94+
@Value("${series.find_series_id_by_yvert_number}")
95+
private String findSeriesIdByYvertNumberSql;
96+
97+
@Value("${series.find_series_id_by_gibbons_number}")
98+
private String findSeriesIdByGibbonsNumberSql;
99+
86100
@Override
87101
public Iterable<SitemapInfoDto> findAllForSitemap() {
88102
return jdbcTemplate.query(
@@ -201,4 +215,64 @@ public long countByGibbonsNumberCode(String gibbonsNumber) {
201215
);
202216
}
203217

218+
@Override
219+
public Optional<Integer> findSeriesIdByMichelNumberCode(String michelNumber) {
220+
try {
221+
Integer seriesId = jdbcTemplate.queryForObject(
222+
findSeriesIdByMichelNumberSql,
223+
Collections.singletonMap("michel_number", michelNumber),
224+
Integer.class
225+
);
226+
return Optional.of(seriesId);
227+
228+
} catch (EmptyResultDataAccessException ignored) {
229+
return Optional.empty();
230+
}
231+
}
232+
233+
@Override
234+
public Optional<Integer> findSeriesIdByScottNumberCode(String scottNumber) {
235+
try {
236+
Integer seriesId = jdbcTemplate.queryForObject(
237+
findSeriesIdByScottNumberSql,
238+
Collections.singletonMap("scott_number", scottNumber),
239+
Integer.class
240+
);
241+
return Optional.of(seriesId);
242+
243+
} catch (EmptyResultDataAccessException ignored) {
244+
return Optional.empty();
245+
}
246+
}
247+
248+
@Override
249+
public Optional<Integer> findSeriesIdByYvertNumberCode(String yvertNumber) {
250+
try {
251+
Integer seriesId = jdbcTemplate.queryForObject(
252+
findSeriesIdByYvertNumberSql,
253+
Collections.singletonMap("yvert_number", yvertNumber),
254+
Integer.class
255+
);
256+
return Optional.of(seriesId);
257+
258+
} catch (EmptyResultDataAccessException ignored) {
259+
return Optional.empty();
260+
}
261+
}
262+
263+
@Override
264+
public Optional<Integer> findSeriesIdByGibbonsNumberCode(String gibbonsNumber) {
265+
try {
266+
Integer seriesId = jdbcTemplate.queryForObject(
267+
findSeriesIdByGibbonsNumberSql,
268+
Collections.singletonMap("gibbons_number", gibbonsNumber),
269+
Integer.class
270+
);
271+
return Optional.of(seriesId);
272+
273+
} catch (EmptyResultDataAccessException ignored) {
274+
return Optional.empty();
275+
}
276+
}
277+
204278
}

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

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818
package ru.mystamps.web.service;
1919

20+
import java.util.Optional;
21+
2022
import ru.mystamps.web.entity.Category;
2123
import ru.mystamps.web.entity.Collection;
2224
import ru.mystamps.web.entity.Country;
@@ -36,10 +38,17 @@ public interface SeriesService {
3638
long countAllStamps();
3739
long countSeriesOf(Collection collection);
3840
long countStampsOf(Collection collection);
41+
3942
long countByMichelNumber(String michelNumberCode);
4043
long countByScottNumber(String scottNumberCode);
4144
long countByYvertNumber(String yvertNumberCode);
4245
long countByGibbonsNumber(String gibbonsNumberCode);
46+
47+
Optional<Integer> findSeriesIdByMichelNumber(String michelNumberCode);
48+
Optional<Integer> findSeriesIdByScottNumber(String scottNumberCode);
49+
Optional<Integer> findSeriesIdByYvertNumber(String yvertNumberCode);
50+
Optional<Integer> findSeriesIdByGibbonsNumber(String gibbonsNumberCode);
51+
4352
Iterable<SeriesInfoDto> findBy(Category category, String lang);
4453
Iterable<SeriesInfoDto> findBy(Country country, String lang);
4554
Iterable<SeriesInfoDto> findBy(Collection collection, String lang);

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

+40
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.Collections;
2121
import java.util.Date;
22+
import java.util.Optional;
2223
import java.util.Set;
2324

2425
import org.springframework.security.access.prepost.PreAuthorize;
@@ -214,6 +215,45 @@ public long countByGibbonsNumber(String gibbonsNumberCode) {
214215
return jdbcSeriesDao.countByGibbonsNumberCode(gibbonsNumberCode);
215216
}
216217

218+
@Override
219+
@Transactional(readOnly = true)
220+
public Optional<Integer> findSeriesIdByMichelNumber(String michelNumberCode) {
221+
Validate.isTrue(michelNumberCode != null, "Michel number code must be non null");
222+
Validate.isTrue(!michelNumberCode.trim().isEmpty(), "Michel number code must be non empty");
223+
224+
return jdbcSeriesDao.findSeriesIdByMichelNumberCode(michelNumberCode);
225+
}
226+
227+
@Override
228+
@Transactional(readOnly = true)
229+
public Optional<Integer> findSeriesIdByScottNumber(String scottNumberCode) {
230+
Validate.isTrue(scottNumberCode != null, "Scott number code must be non null");
231+
Validate.isTrue(!scottNumberCode.trim().isEmpty(), "Scott number code must be non empty");
232+
233+
return jdbcSeriesDao.findSeriesIdByScottNumberCode(scottNumberCode);
234+
}
235+
236+
@Override
237+
@Transactional(readOnly = true)
238+
public Optional<Integer> findSeriesIdByYvertNumber(String yvertNumberCode) {
239+
Validate.isTrue(yvertNumberCode != null, "Yvert number code must be non null");
240+
Validate.isTrue(!yvertNumberCode.trim().isEmpty(), "Yvert number code must be non empty");
241+
242+
return jdbcSeriesDao.findSeriesIdByYvertNumberCode(yvertNumberCode);
243+
}
244+
245+
@Override
246+
@Transactional(readOnly = true)
247+
public Optional<Integer> findSeriesIdByGibbonsNumber(String gibbonsNumberCode) {
248+
Validate.isTrue(gibbonsNumberCode != null, "Gibbons number code must be non null");
249+
Validate.isTrue(
250+
!gibbonsNumberCode.trim().isEmpty(),
251+
"Gibbons number code must be non empty"
252+
);
253+
254+
return jdbcSeriesDao.findSeriesIdByGibbonsNumberCode(gibbonsNumberCode);
255+
}
256+
217257
@Override
218258
@Transactional(readOnly = true)
219259
public Iterable<SeriesInfoDto> findBy(Category category, String lang) {

src/main/resources/sql/series_dao_queries.properties

+29
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,32 @@ series.count_stamps_by_gibbons_number = \
124124
SELECT COUNT(*) \
125125
FROM gibbons_catalog \
126126
WHERE code = :gibbons_number
127+
128+
series.find_series_id_by_michel_number = \
129+
SELECT smc.series_id AS series_id \
130+
FROM series_michel_catalog smc \
131+
JOIN michel_catalog mc \
132+
ON mc.id = smc.michel_id \
133+
WHERE mc.code = :michel_number
134+
135+
series.find_series_id_by_scott_number = \
136+
SELECT ssc.series_id AS series_id \
137+
FROM series_scott_catalog ssc \
138+
JOIN scott_catalog mc \
139+
ON mc.id = ssc.scott_id \
140+
WHERE mc.code = :scott_number
141+
142+
series.find_series_id_by_yvert_number = \
143+
SELECT syc.series_id AS series_id \
144+
FROM series_yvert_catalog syc \
145+
JOIN yvert_catalog mc \
146+
ON mc.id = syc.yvert_id \
147+
WHERE mc.code = :yvert_number
148+
149+
series.find_series_id_by_gibbons_number = \
150+
SELECT sgc.series_id AS series_id \
151+
FROM series_gibbons_catalog sgc \
152+
JOIN gibbons_catalog mc \
153+
ON mc.id = sgc.gibbons_id \
154+
WHERE mc.code = :gibbons_number
155+

0 commit comments

Comments
 (0)