Skip to content

Commit ccd457e

Browse files
committed
Series import: extract info about perforation.
Fix #782
1 parent 72ac39e commit ccd457e

20 files changed

+149
-9
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public String processRequestImportForm(
8787
return redirectTo(Url.REQUEST_IMPORT_PAGE, requestId);
8888
}
8989

90+
@SuppressWarnings({ "PMD.ModifiedCyclomaticComplexity", "PMD.NPathComplexity" })
9091
@GetMapping(Url.REQUEST_IMPORT_PAGE)
9192
public String showRequestAndImportSeriesForm(
9293
@PathVariable("id") Integer requestId,
@@ -131,6 +132,9 @@ public String showRequestAndImportSeriesForm(
131132
if (parsedData.getQuantity() != null) {
132133
form.setQuantity(parsedData.getQuantity());
133134
}
135+
if (parsedData.getPerforated() != null) {
136+
form.setPerforated(parsedData.getPerforated());
137+
}
134138
}
135139

136140
model.addAttribute("importSeriesForm", form);

src/main/java/ru/mystamps/web/controller/event/DownloadingSucceededEventListener.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ public void onApplicationEvent(DownloadingSucceeded event) {
9191
info.getCountryName(),
9292
info.getImageUrl(),
9393
info.getIssueDate(),
94-
info.getQuantity()
94+
info.getQuantity(),
95+
info.getPerforated()
9596
);
9697
importService.saveParsedData(requestId, data);
9798
}

src/main/java/ru/mystamps/web/dao/dto/ParsedDataDto.java

+1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ public class ParsedDataDto {
2828
private final String imageUrl;
2929
private final Integer issueYear;
3030
private final Integer quantity;
31+
private final Boolean perforated;
3132
}

src/main/java/ru/mystamps/web/dao/dto/SaveParsedDataDbDto.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class SaveParsedDataDbDto {
3232
private String imageUrl;
3333
private Integer releaseYear;
3434
private Integer quantity;
35+
private Boolean perforated;
3536
private Date createdAt;
3637
private Date updatedAt;
3738

@@ -40,7 +41,8 @@ public boolean hasAtLeastOneFieldFilled() {
4041
|| countryId != null
4142
|| imageUrl != null
4243
|| releaseYear != null
43-
|| quantity != null;
44+
|| quantity != null
45+
|| perforated != null;
4446
}
4547

4648
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ public void addParsedContent(Integer requestId, SaveParsedDataDbDto data) {
212212
params.put("created_at", data.getCreatedAt());
213213
params.put("updated_at", data.getUpdatedAt());
214214
params.put("quantity", data.getQuantity());
215+
params.put("perforated", data.getPerforated());
215216

216217
KeyHolder holder = new GeneratedKeyHolder();
217218

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

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ public static Integer getInteger(ResultSet resultSet, String fieldName) throws S
3838
return Integer.valueOf(value);
3939
}
4040

41+
@SuppressWarnings("PMD.PrematureDeclaration")
42+
public static Boolean getBoolean(ResultSet resultSet, String fieldName) throws SQLException {
43+
boolean value = resultSet.getBoolean(fieldName);
44+
if (resultSet.wasNull()) {
45+
return null;
46+
}
47+
48+
return Boolean.valueOf(value);
49+
}
50+
4151
/**
4252
* @author Sergey Chechenev
4353
*/

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,9 @@ public static ParsedDataDto forParsedDataDto(ResultSet rs, int i) throws SQLExce
274274
String imageUrl = rs.getString("image_url");
275275
Integer releaseYear = JdbcUtils.getInteger(rs, "release_year");
276276
Integer quantity = JdbcUtils.getInteger(rs, "quantity");
277+
Boolean perforated = JdbcUtils.getBoolean(rs, "perforated");
277278

278-
return new ParsedDataDto(category, country, imageUrl, releaseYear, quantity);
279+
return new ParsedDataDto(category, country, imageUrl, releaseYear, quantity, perforated);
279280
}
280281

281282
public static ImportRequestInfo forImportRequestInfo(ResultSet rs, int i) throws SQLException {

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

+5
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ public void saveParsedData(Integer requestId, RawParsedDataDto data) {
190190
processedData.setQuantity(quantity);
191191
}
192192

193+
Boolean perforated = extractorService.extractPerforated(data.getPerforated());
194+
if (perforated != null) {
195+
processedData.setPerforated(perforated);
196+
}
197+
193198
// IMPORTANT: don't add code that modifies database above this line!
194199
// @todo #684 Series import: add integration test
195200
// for the case when parsed value don't match database

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

+1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ public interface SeriesInfoExtractorService {
2424
List<Integer> extractCountry(String fragment);
2525
Integer extractReleaseYear(String fragment);
2626
Integer extractQuantity(String fragment);
27+
Boolean extractPerforated(String fragment);
2728
}

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

+21
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,25 @@ public Integer extractQuantity(String fragment) {
164164
return null;
165165
}
166166

167+
// @todo #782 SeriesInfoExtractorServiceImpl.extractPerforated(): add unit tests
168+
// @todo #782 Series import: add integration test for extracting perforation flag
169+
@Override
170+
public Boolean extractPerforated(String fragment) {
171+
if (StringUtils.isBlank(fragment)) {
172+
return null;
173+
}
174+
175+
log.debug("Determining perforation from a fragment: '{}'", fragment);
176+
177+
boolean withoutPerforation = StringUtils.contains(fragment, "б/з");
178+
if (withoutPerforation) {
179+
log.debug("Perforation is false");
180+
return Boolean.FALSE;
181+
}
182+
183+
log.debug("Could not extract perforation info from a fragment");
184+
185+
return null;
186+
}
187+
167188
}

src/main/java/ru/mystamps/web/service/dto/RawParsedDataDto.java

+1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ public class RawParsedDataDto {
2828
private final String imageUrl;
2929
private final String releaseYear;
3030
private final String quantity;
31+
private final String perforated;
3132
}

src/main/java/ru/mystamps/web/util/extractor/SeriesInfo.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class SeriesInfo {
3535
private String imageUrl;
3636
private String issueDate;
3737
private String quantity;
38+
private String perforated;
3839

3940
/**
4041
* Check whether any info about a series is available.
@@ -44,7 +45,8 @@ public boolean isEmpty() {
4445
&& countryName == null
4546
&& imageUrl == null
4647
&& issueDate == null
47-
&& quantity == null;
48+
&& quantity == null
49+
&& perforated == null;
4850
}
4951

5052
}

src/main/java/ru/mystamps/web/util/extractor/SiteParser.java

+18
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public SeriesInfo parse(String htmlPage) {
137137
info.setImageUrl(extractImageUrl(body));
138138
info.setIssueDate(extractIssueDate(body));
139139
info.setQuantity(extractQuantity(body));
140+
info.setPerforated(extractPerforated(body));
140141

141142
return info;
142143
}
@@ -226,4 +227,21 @@ protected String extractQuantity(Element body) {
226227
return quantity;
227228
}
228229

230+
// @todo #782 SiteParser: reduce duplication between extractQuantity() and extractPerforated()
231+
protected String extractPerforated(Element body) {
232+
String locator = shortDescriptionLocator;
233+
if (locator == null) {
234+
return null;
235+
}
236+
237+
Element elem = body.selectFirst(locator);
238+
if (elem == null) {
239+
return null;
240+
}
241+
242+
String perforated = elem.text();
243+
LOG.debug("Extracted perforated flag: '{}'", perforated);
244+
return perforated;
245+
}
246+
229247
}

src/main/resources/liquibase/version/0.4.xml

+1
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@
4545
<include file="0.4/2017-12-21--zagorski_catalog.xml" relativeToChangelogFile="true" />
4646
<include file="0.4/2017-12-30--series_import_requests_url_length2.xml" relativeToChangelogFile="true" />
4747
<include file="0.4/2018-01-01--add_quantity_to_parsed_data.xml" relativeToChangelogFile="true" />
48+
<include file="0.4/2018-01-01--add_perforated_to_parsed_data.xml" relativeToChangelogFile="true" />
4849

4950
</databaseChangeLog>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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.1.xsd">
7+
8+
<changeSet id="add-perforated-field-to-series_import_parsed_data" author="php-coder" context="scheme">
9+
10+
<addColumn tableName="series_import_parsed_data">
11+
<column name="perforated" type="BOOLEAN" afterColumn="image_url" />
12+
</addColumn>
13+
14+
</changeSet>
15+
16+
</databaseChangeLog>

src/main/resources/sql/series_import_request_dao_queries.properties

+3
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ INSERT \
8989
, image_url \
9090
, release_year \
9191
, quantity \
92+
, perforated \
9293
, created_at \
9394
, updated_at \
9495
) \
@@ -99,6 +100,7 @@ VALUES \
99100
, :image_url \
100101
, :release_year \
101102
, :quantity \
103+
, :perforated \
102104
, :created_at \
103105
, :updated_at \
104106
)
@@ -113,6 +115,7 @@ series_import_requests.find_parsed_data_by_request_id = \
113115
, CASE WHEN 'ru' = :lang THEN COALESCE(count.name_ru, count.name) ELSE count.name END AS country_name \
114116
, pd.release_year \
115117
, pd.quantity \
118+
, pd.perforated \
116119
FROM series_import_parsed_data pd \
117120
LEFT JOIN categories cat \
118121
ON cat.id = pd.category_id \

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

+10-3
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ class SeriesImportServiceImplTest extends Specification {
411411
Random.countryName(),
412412
null, /* imageUrl */
413413
Random.issueYear().toString(),
414-
Random.quantity().toString()
414+
Random.quantity().toString(),
415+
String.valueOf(Random.perforated())
415416
)
416417
and:
417418
extractorService.extractCategory(_ as String) >> Collections.emptyList()
@@ -436,7 +437,8 @@ class SeriesImportServiceImplTest extends Specification {
436437
Random.countryName(),
437438
expectedImageUrl,
438439
Random.issueYear().toString(),
439-
Random.quantity().toString()
440+
Random.quantity().toString(),
441+
String.valueOf(Random.perforated())
440442
)
441443
and:
442444
extractorService.extractCategory(_ as String) >> Collections.emptyList()
@@ -467,13 +469,15 @@ class SeriesImportServiceImplTest extends Specification {
467469
Integer expectedCategoryId = expectedCategoryIds.get(0)
468470
Integer expectedCountryId = expectedCountryIds.get(0)
469471
Integer expectedQuantity = Random.quantity()
472+
Boolean expectedPerforated = Random.perforated()
470473
and:
471474
RawParsedDataDto parsedData = new RawParsedDataDto(
472475
expectedCategoryName,
473476
expectedCountryName,
474477
Random.url(),
475478
expectedReleaseYear.toString(),
476-
expectedQuantity.toString()
479+
expectedQuantity.toString(),
480+
expectedPerforated.toString()
477481
)
478482
when:
479483
service.saveParsedData(expectedRequestId, parsedData)
@@ -485,6 +489,8 @@ class SeriesImportServiceImplTest extends Specification {
485489
1 * extractorService.extractReleaseYear(expectedReleaseYear.toString()) >> expectedReleaseYear
486490
and:
487491
1 * extractorService.extractQuantity(expectedQuantity.toString()) >> expectedQuantity
492+
and:
493+
1 * extractorService.extractPerforated(expectedPerforated.toString()) >> expectedPerforated
488494
and:
489495
1 * seriesImportDao.addParsedContent(
490496
expectedRequestId,
@@ -493,6 +499,7 @@ class SeriesImportServiceImplTest extends Specification {
493499
assert saveParsedData?.countryId == expectedCountryId
494500
assert saveParsedData?.releaseYear == expectedReleaseYear
495501
assert saveParsedData?.quantity == expectedQuantity
502+
assert saveParsedData?.perforated == expectedPerforated
496503
return true
497504
}
498505
)

src/test/java/ru/mystamps/web/service/TestObjects.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ public static ParsedDataDto createParsedDataDto() {
203203
new LinkEntityDto(Random.id(), countrySlug, countryName),
204204
Random.url(),
205205
Random.issueYear(),
206-
Random.quantity()
206+
Random.quantity(),
207+
Random.perforated()
207208
);
208209
}
209210

@@ -213,7 +214,8 @@ public static RawParsedDataDto createRawParsedDataDto() {
213214
Random.countryName(),
214215
Random.url(),
215216
Random.issueYear().toString(),
216-
Random.quantity().toString()
217+
Random.quantity().toString(),
218+
String.valueOf(Random.perforated())
217219
);
218220
}
219221

src/test/java/ru/mystamps/web/tests/Random.java

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import ru.mystamps.web.service.TestObjects;
4040
import ru.mystamps.web.validation.ValidationRules;
4141

42+
import static io.qala.datagen.RandomShortApi.bool;
4243
import static io.qala.datagen.RandomShortApi.integer;
4344
import static io.qala.datagen.RandomShortApi.sample;
4445
import static io.qala.datagen.RandomShortApi.sampleMultiple;
@@ -151,6 +152,10 @@ public static Integer quantity() {
151152
).integer();
152153
}
153154

155+
public static boolean perforated() {
156+
return bool();
157+
}
158+
154159
public static String importRequestStatus() {
155160
return sample(STATUSES);
156161
}

src/test/java/ru/mystamps/web/util/extractor/SiteParserTest.java

+38
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,44 @@ public void extractQuantityShouldReturnTextOfShortDescriptionLocator() {
674674
assertThat(msg, quantity, equalTo(expectedQuantity));
675675
}
676676

677+
//
678+
// Tests for extractPerforated()
679+
//
680+
681+
@Test
682+
public void extractPerforatedShouldReturnNullWhenShortDescriptionLocatorIsNotSet() {
683+
parser.setShortDescriptionLocator(null);
684+
Element doc = createEmptyDocument();
685+
686+
String perforated = parser.extractPerforated(doc);
687+
688+
assertThat(perforated, is(nullValue()));
689+
}
690+
691+
@Test
692+
public void extractPerforatedShouldReturnNullWhenElementNotFound() {
693+
parser.setShortDescriptionLocator(Random.jsoupLocator());
694+
Element doc = createEmptyDocument();
695+
696+
String perforated = parser.extractPerforated(doc);
697+
698+
assertThat(perforated, is(nullValue()));
699+
}
700+
701+
@Test
702+
public void extractPerforatedShouldReturnTextOfShortDescriptionLocator() {
703+
parser.setShortDescriptionLocator("#desc");
704+
705+
String expectedValue = String.valueOf(Random.perforated());
706+
String html = String.format("<div id='desc'>%s</div>", expectedValue);
707+
Element doc = createDocumentFromText(html);
708+
709+
String perforated = parser.extractPerforated(doc);
710+
711+
String msg = String.format("couldn't extract perforated flag from '%s'", doc);
712+
assertThat(msg, perforated, equalTo(expectedValue));
713+
}
714+
677715
private static String describe(SiteParser parser) {
678716
StringBuilder sb = new StringBuilder();
679717
sb.append("SiteParser[name=")

0 commit comments

Comments
 (0)