Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 7bf2464a

Přidáno uživatelem Jakub Šmíd před více než 2 roky(ů)

Added controller and some tests for external catalog

re #9624

Zobrazit rozdíly:

backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItem.java
119 119

  
120 120
        this.name = csvFields.get(1);
121 121
        Set<String> stringList = processListField(csvFields.get(2));
122
        stringList.add(this.name);
122 123
        this.alternativeNames = stringList.stream().map(s -> new AlternativeName(s, this)).collect(Collectors.toSet());
123 124

  
124 125
        this.certainty = processIntField(csvFields.get(3));
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImpl.java
224 224
    }
225 225

  
226 226
    /**
227
     * Converts catalog DTO to catalog entity
227
     * Converts catalog item DTO to catalog item entity
228 228
     *
229
     * @param catalogItemDto catalog DTO
230
     * @param catalogItem    catalog entity
229
     * @param catalogItemDto catalog item DTO
230
     * @param catalogItem    catalog item entity
231 231
     */
232 232
    private void convertDtoToEntity(CatalogItemDto catalogItemDto, CatalogItem catalogItem) {
233 233
        catalogItem.setName(catalogItemDto.getName());
......
247 247
        catalogItem.getCountries().addAll(catalogItemDto.getCountries()
248 248
                .stream().map(s -> new Country(s, catalogItem)).collect(Collectors.toSet()));
249 249

  
250
        catalogItemDto.getAlternativeNames().add(catalogItemDto.getName());
250 251
        catalogItem.getAlternativeNames().clear();
251 252
        catalogItem.getAlternativeNames().addAll(catalogItemDto.getAlternativeNames()
252 253
                .stream().map(s -> new AlternativeName(s, catalogItem)).collect(Collectors.toSet()));
......
259 260
    }
260 261

  
261 262
    /**
262
     * Converts catalog entity to catalog DTO
263
     * Converts catalog item entity to catalog item DTO
263 264
     *
264
     * @param catalogItem catalog entity
265
     * @return catalog DTO
265
     * @param catalogItem catalog item entity
266
     * @return catalog item DTO
266 267
     */
267 268
    private CatalogItemDto convertEntityToDto(CatalogItem catalogItem) {
268 269
        CatalogItemDto catalogItemDto = new CatalogItemDto();
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogController.java
1 1
package cz.zcu.kiv.backendapi.external;
2 2

  
3
import io.swagger.v3.oas.annotations.Operation;
3 4
import lombok.RequiredArgsConstructor;
4
import org.springframework.web.bind.annotation.PostMapping;
5
import org.springframework.web.bind.annotation.RequestMapping;
6
import org.springframework.web.bind.annotation.RestController;
5
import org.springframework.http.HttpStatus;
6
import org.springframework.http.ResponseEntity;
7
import org.springframework.web.bind.annotation.*;
8

  
9
import java.util.List;
7 10

  
8 11
/**
9 12
 * Controller for external catalog
......
16 19
    /**
17 20
     * External catalog service
18 21
     */
19
    private final IExternalCatalogService externalCatalogService;
22
    private final IExternalCatalogItemService externalCatalogService;
20 23

  
21 24
    @PostMapping("")
25
    @Operation(summary = "updates external catalog")
22 26
    public void updateCatalog() {
23 27
        externalCatalogService.updateCatalog();
24 28
    }
29

  
30
    /**
31
     * Returns external catalog items satisfying given filter
32
     *
33
     * @param name   name
34
     * @param source source
35
     * @return list of external catalog items satisfying given filter
36
     */
37
    @GetMapping("")
38
    @Operation(summary = "returns external catalog items based on filter")
39
    public ResponseEntity<List<ExternalCatalogItem>> getCatalog(@RequestParam String name, @RequestParam ExternalSource source) {
40
        return new ResponseEntity<>(externalCatalogService.getCatalog(name, source), HttpStatus.OK);
41
    }
25 42
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogItem.java
1 1
package cz.zcu.kiv.backendapi.external;
2 2

  
3
import lombok.EqualsAndHashCode;
4
import lombok.Getter;
5
import lombok.NoArgsConstructor;
6
import lombok.Setter;
3
import io.swagger.v3.oas.annotations.media.Schema;
4
import lombok.*;
7 5

  
8 6
import javax.persistence.*;
9 7
import java.util.*;
......
18 16
@Setter
19 17
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
20 18
@NoArgsConstructor
19
@AllArgsConstructor
21 20
@Entity
22 21
@Table(name = "external_catalog_items")
22
@Schema(name = "ExternalCatalogItemDto")
23 23
public class ExternalCatalogItem {
24 24
    /**
25 25
     * Map where key is country code and value is name of country
......
116 116
    @Column(length = 20000)
117 117
    private Set<String> names = new HashSet<>();
118 118

  
119

  
119 120
    /**
120 121
     * Feature code
121 122
     */
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogItemItemServiceImpl.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import com.zaxxer.hikari.HikariDataSource;
4
import lombok.RequiredArgsConstructor;
5
import lombok.extern.slf4j.Slf4j;
6
import org.apache.commons.csv.CSVFormat;
7
import org.apache.commons.csv.CSVParser;
8
import org.apache.commons.csv.CSVRecord;
9
import org.apache.tomcat.util.http.fileupload.FileUtils;
10
import org.springframework.stereotype.Service;
11
import org.springframework.transaction.annotation.Transactional;
12

  
13
import javax.persistence.Table;
14
import java.io.*;
15
import java.net.URL;
16
import java.nio.charset.StandardCharsets;
17
import java.nio.file.Files;
18
import java.nio.file.Paths;
19
import java.sql.Connection;
20
import java.sql.PreparedStatement;
21
import java.util.ArrayList;
22
import java.util.List;
23
import java.util.concurrent.Callable;
24
import java.util.concurrent.ExecutorService;
25
import java.util.concurrent.Executors;
26
import java.util.stream.Collectors;
27
import java.util.zip.GZIPInputStream;
28
import java.util.zip.ZipEntry;
29
import java.util.zip.ZipInputStream;
30

  
31
/**
32
 * External catalog item service implementation
33
 */
34
@Service
35
@Transactional
36
@RequiredArgsConstructor
37
@Slf4j
38
public class ExternalCatalogItemItemServiceImpl implements IExternalCatalogItemService {
39
    /**
40
     * Buffer size
41
     */
42
    public static final int BUFFER_SIZE = 1024;
43
    /**
44
     * Directory where files for external directory will be stored
45
     */
46
    private static final String DIRECTORY_FOR_EXTERNAL_FILES = "sources";
47
    /**
48
     * URL for Pleiades file
49
     */
50
    private static final String PLEIADES_FILE_URL = "https://atlantides.org/downloads/pleiades/dumps/pleiades-names-latest.csv.gz";
51
    /**
52
     * Name of Pleiades file
53
     */
54
    private static final String PLEIADES_FILE_NAME = "pleiades-names-latest.csv";
55
    /**
56
     * URL for Pleiades file – needs to be formatted (more sources)
57
     */
58
    private static final String GEONAMES_FILE_URL = "https://download.geonames.org/export/dump/%s.zip";
59
    /**
60
     * Name of GeoNames file – needs to be formatted (more sources)
61
     */
62
    private static final String GEONAMES_FILE_NAME = "%s.txt";
63
    /**
64
     * URL for CIGS file
65
     */
66
    private static final String CIGS_FILE_URL = "https://zenodo.org/record/5642899/files/CIGS_v1_4_20211101.csv";
67
    /**
68
     * Name of CIGS file
69
     */
70
    private static final String CIGS_FILE_NAME = "CIGS_v1_4_20211101.csv";
71
    /**
72
     * Batch size for saving items
73
     */
74
    private static final int BATCH_SIZE = 5000;
75

  
76
    /**
77
     * Regex for one arbitrary character in string
78
     */
79
    private static final String WILDCARD_CHARACTER_REGEX = "\\?";
80

  
81
    /**
82
     * Regex for one arbitrary character in string used in SQL
83
     */
84
    private static final String WILDCARD_CHARACTER_REGEX_SQL = "_";
85

  
86
    /**
87
     * Regex for any number of arbitrary characters in string
88
     */
89
    private static final String WILDCARD_CHARACTERS_REGEX = "\\*";
90

  
91
    /**
92
     * Regex for any number of arbitrary characters in string used in SQL
93
     */
94
    private static final String WILDCARD_CHARACTERS_REGEX_SQL = "%";
95

  
96
    /**
97
     * External catalog repository
98
     */
99
    private final ExternalCatalogItemRepository externalCatalogItemRepository;
100

  
101
    /**
102
     * Hikari data source
103
     */
104
    private final HikariDataSource hikariDataSource;
105

  
106
    /**
107
     * Set to string convertor
108
     */
109
    private final SetToStringConverter setToStringConverter;
110

  
111

  
112
    @Override
113
    public void updateCatalog() {
114
        log.info("Updating external catalog");
115
        try {
116
            Files.createDirectories(Paths.get(DIRECTORY_FOR_EXTERNAL_FILES)); // creates directory if not exists
117
            FileUtils.cleanDirectory(new File(DIRECTORY_FOR_EXTERNAL_FILES)); // cleans the directory
118
            externalCatalogItemRepository.deleteAll(); // clears database – updated list will be stored later
119
            addPleiadesSource();
120
            addGeonamesSources();
121
            addCigsSources();
122
        } catch (Exception e) {
123
            e.printStackTrace();
124
        }
125
        log.info("External catalog updated");
126
    }
127

  
128
    @Override
129
    public List<ExternalCatalogItem> getCatalog(String name, ExternalSource source) {
130
        name = WILDCARD_CHARACTERS_REGEX_SQL +
131
                name.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_SQL).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_SQL) +
132
                WILDCARD_CHARACTERS_REGEX_SQL;
133
        return externalCatalogItemRepository.getFilteredExternalCatalog(name, source.name());
134
    }
135

  
136
    /**
137
     * Downloads, extracts and reads Pleiades sources and saves them to database
138
     */
139
    private void addPleiadesSource() {
140
        List<ExternalCatalogItem> externalCatalogItems = new ArrayList<>();
141
        byte[] buffer = new byte[BUFFER_SIZE];
142
        File pleiadesFile = new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), PLEIADES_FILE_NAME);
143
        try (InputStream fileIn = new URL(PLEIADES_FILE_URL).openStream();
144
             GZIPInputStream gZIPInputStream = new GZIPInputStream(fileIn);
145
             FileOutputStream fileOutputStream = new FileOutputStream(pleiadesFile)) {
146

  
147
            int bytes_read;
148

  
149
            while ((bytes_read = gZIPInputStream.read(buffer)) > 0) {
150
                fileOutputStream.write(buffer, 0, bytes_read);
151
            }
152

  
153
            log.info("The Pleiades file was decompressed successfully");
154

  
155
        } catch (IOException ex) {
156
            ex.printStackTrace();
157
        }
158

  
159
        try (InputStream csvData = new FileInputStream(pleiadesFile)) {
160
            CSVParser parser = CSVParser.parse(csvData, StandardCharsets.UTF_8, CSVFormat.Builder.create(CSVFormat.DEFAULT)
161
                    .setHeader()
162
                    .setSkipHeaderRecord(true)
163
                    .build());
164
            for (CSVRecord csvRecord : parser) {
165
                ExternalCatalogItem e = new ExternalCatalogItem(csvRecord.toList(), ExternalSource.PLEIADES);
166
                externalCatalogItems.add(e);
167
            }
168

  
169
        } catch (IOException ex) {
170
            ex.printStackTrace();
171
        }
172
        saveAllWithThreads(externalCatalogItems);
173
    }
174

  
175
    /**
176
     * Downloads, extracts and reads GeoNames sources and saves them to database
177
     */
178
    private void addGeonamesSources() {
179
        byte[] buffer = new byte[BUFFER_SIZE];
180
        for (String countryCode : ExternalCatalogItem.COUNTRY_CODES.keySet()) {
181
            List<ExternalCatalogItem> externalCatalogItems = new ArrayList<>();
182
            // Downloads file from URL and extracts it
183
            String url = String.format(GEONAMES_FILE_URL, countryCode);
184
            try (ZipInputStream zis = new ZipInputStream(new URL(url).openStream())) {
185
                ZipEntry zipEntry = zis.getNextEntry();
186
                while (zipEntry != null) {
187
                    FileOutputStream fileOutputStream = new FileOutputStream(new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), zipEntry.getName()));
188
                    int bytes_read;
189
                    while ((bytes_read = zis.read(buffer)) > 0) {
190
                        fileOutputStream.write(buffer, 0, bytes_read);
191
                    }
192
                    zipEntry = zis.getNextEntry();
193
                    fileOutputStream.close();
194
                }
195
            } catch (IOException e) {
196
                e.printStackTrace();
197
            }
198

  
199
            log.info("The GeoNames file with country code " + countryCode + " was decompressed successfully");
200

  
201
            // Reads file and adds catalog items to list
202
            File geoNamesFile = new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), String.format(GEONAMES_FILE_NAME, countryCode));
203
            try (BufferedReader reader = new BufferedReader(new FileReader(geoNamesFile))) {
204
                String line;
205
                while ((line = reader.readLine()) != null) {
206
                    ExternalCatalogItem e = new ExternalCatalogItem(List.of(line.split("\t")), ExternalSource.GEONAMES);
207
                    externalCatalogItems.add(e);
208
                }
209
            } catch (IOException e) {
210
                e.printStackTrace();
211
            }
212
            saveAllWithThreads(externalCatalogItems);
213
        }
214
    }
215

  
216
    /**
217
     * Downloads and reads CIGS sources and saves them to database
218
     */
219
    private void addCigsSources() {
220
        List<ExternalCatalogItem> externalCatalogItems = new ArrayList<>();
221
        byte[] buffer = new byte[BUFFER_SIZE];
222
        File cigsFile = new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), CIGS_FILE_NAME);
223

  
224
        try (InputStream inputStream = new URL(CIGS_FILE_URL).openStream();
225
             FileOutputStream fileOutputStream = new FileOutputStream(cigsFile)) {
226
            int bytes_read;
227

  
228
            while ((bytes_read = inputStream.read(buffer)) > 0) {
229

  
230
                fileOutputStream.write(buffer, 0, bytes_read);
231
            }
232
        } catch (IOException e) {
233
            e.printStackTrace();
234
        }
235

  
236
        log.info("The CIGS file was downloaded successfully");
237

  
238
        try (InputStream csvData = new FileInputStream(cigsFile)) {
239
            CSVParser parser = CSVParser.parse(csvData, StandardCharsets.UTF_8, CSVFormat.Builder.create(CSVFormat.DEFAULT)
240
                    .setHeader()
241
                    .setSkipHeaderRecord(true)
242
                    .build());
243
            for (CSVRecord csvRecord : parser) {
244
                ExternalCatalogItem e = new ExternalCatalogItem(csvRecord.toList(), ExternalSource.CIGS);
245
                externalCatalogItems.add(e);
246
            }
247
        } catch (IOException e) {
248
            e.printStackTrace();
249
        }
250
        saveAllWithThreads(externalCatalogItems);
251
    }
252

  
253
    /**
254
     * Creates list of lists of external catalog items divided by batch size
255
     *
256
     * @param externalCatalogItems list of external catalog items
257
     * @return divided list of lists of external catalog items
258
     */
259
    private List<List<ExternalCatalogItem>> createSublist(List<ExternalCatalogItem> externalCatalogItems) {
260
        List<List<ExternalCatalogItem>> listOfSubList = new ArrayList<>();
261
        for (int i = 0; i < externalCatalogItems.size(); i += BATCH_SIZE) {
262
            if (i + BATCH_SIZE <= externalCatalogItems.size()) {
263
                listOfSubList.add(externalCatalogItems.subList(i, i + BATCH_SIZE));
264
            } else {
265
                listOfSubList.add(externalCatalogItems.subList(i, externalCatalogItems.size()));
266
            }
267
        }
268
        return listOfSubList;
269
    }
270

  
271
    /**
272
     * Divides list of external catalog items to sublist, creates threads (for saving sublists in batch) and executes them
273
     *
274
     * @param externalCatalogItems list of external catalog items
275
     */
276
    private void saveAllWithThreads(List<ExternalCatalogItem> externalCatalogItems) {
277
        ExecutorService executorService = Executors.newFixedThreadPool(hikariDataSource.getMaximumPoolSize());
278
        List<List<ExternalCatalogItem>> subList = createSublist(externalCatalogItems);
279
        List<Callable<Void>> callables = subList.stream().map(sublist ->
280
                (Callable<Void>) () -> {
281
                    saveAllInBatch(sublist);
282
                    return null;
283
                }).collect(Collectors.toList());
284
        try {
285
            executorService.invokeAll(callables);
286
        } catch (InterruptedException e) {
287
            e.printStackTrace();
288
        }
289
    }
290

  
291
    /**
292
     * Saves external catalog items in batch
293
     *
294
     * @param externalCatalogItems list of external catalog items
295
     */
296
    private void saveAllInBatch(List<ExternalCatalogItem> externalCatalogItems) {
297
        String sqlExternalCatalogItem = String.format("INSERT INTO %s (id, external_source, latitude, longitude, location_precision, max_date, " +
298
                "min_date, time_period_keys, pid, names, feature_code, country, accuracy, geoname_id, pleiades_id, osm_id) " +
299
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?,  ?, ?, ?, ?, ?, ?, ?, ?)", ExternalCatalogItem.class.getAnnotation(Table.class).name());
300
        try (Connection connection = hikariDataSource.getConnection();
301
             PreparedStatement statementExternalCatalogItem = connection.prepareStatement(sqlExternalCatalogItem)) {
302
            int counter = 0;
303
            for (ExternalCatalogItem item : externalCatalogItems) {
304
                statementExternalCatalogItem.clearParameters();
305
                statementExternalCatalogItem.setObject(1, item.getId());
306
                statementExternalCatalogItem.setString(2, item.getExternalSource().name());
307
                statementExternalCatalogItem.setObject(3, item.getLatitude());
308
                statementExternalCatalogItem.setObject(4, item.getLongitude());
309
                statementExternalCatalogItem.setString(5, item.getLocationPrecision());
310
                statementExternalCatalogItem.setObject(6, item.getMaxDate());
311
                statementExternalCatalogItem.setObject(7, item.getMinDate());
312
                statementExternalCatalogItem.setString(8, item.getTimePeriodKeys());
313
                statementExternalCatalogItem.setString(9, item.getPid());
314
                statementExternalCatalogItem.setString(10, setToStringConverter.convertToDatabaseColumn(item.getNames()));
315
                statementExternalCatalogItem.setString(11, item.getFeatureCode());
316
                statementExternalCatalogItem.setString(12, item.getCountry());
317
                statementExternalCatalogItem.setObject(13, item.getAccuracy());
318
                statementExternalCatalogItem.setObject(14, item.getGeonameId());
319
                statementExternalCatalogItem.setObject(15, item.getPleiadesId());
320
                statementExternalCatalogItem.setObject(16, item.getOsmId());
321
                statementExternalCatalogItem.addBatch();
322

  
323
                counter++;
324
                if (counter % BATCH_SIZE == 0 || counter == externalCatalogItems.size()) {
325
                    statementExternalCatalogItem.executeBatch();
326
                    statementExternalCatalogItem.clearBatch();
327
                }
328
            }
329
        } catch (Exception e) {
330
            e.printStackTrace();
331
        }
332
    }
333
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogItemRepository.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import org.springframework.data.jpa.repository.JpaRepository;
4
import org.springframework.data.jpa.repository.Query;
5
import org.springframework.stereotype.Repository;
6

  
7
import java.util.List;
8
import java.util.UUID;
9

  
10
/**
11
 * External catalog repository
12
 */
13
@Repository
14
public interface ExternalCatalogItemRepository extends JpaRepository<ExternalCatalogItem, UUID> {
15

  
16
    /**
17
     * Returns list of external catalog items satisfying given filter
18
     *
19
     * @param name           name
20
     * @param externalSource source
21
     * @return list of external catalog items satisfying given filter
22
     */
23
    @Query(value = "SELECT * FROM external_catalog_items e WHERE UPPER(e.names) LIKE UPPER(?1) AND e.external_source = ?2", nativeQuery = true)
24
    List<ExternalCatalogItem> getFilteredExternalCatalog(String name, String externalSource);
25
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogRepository.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import org.springframework.data.jpa.repository.JpaRepository;
4
import org.springframework.stereotype.Repository;
5

  
6
import java.util.UUID;
7

  
8
/**
9
 * External catalog repository
10
 */
11
@Repository
12
public interface ExternalCatalogRepository extends JpaRepository<ExternalCatalogItem, UUID> {
13
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogServiceImpl.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import com.zaxxer.hikari.HikariDataSource;
4
import lombok.RequiredArgsConstructor;
5
import lombok.extern.slf4j.Slf4j;
6
import org.apache.commons.csv.CSVFormat;
7
import org.apache.commons.csv.CSVParser;
8
import org.apache.commons.csv.CSVRecord;
9
import org.apache.tomcat.util.http.fileupload.FileUtils;
10
import org.springframework.stereotype.Service;
11
import org.springframework.transaction.annotation.Transactional;
12

  
13
import javax.persistence.Table;
14
import java.io.*;
15
import java.net.URL;
16
import java.nio.charset.StandardCharsets;
17
import java.nio.file.Files;
18
import java.nio.file.Paths;
19
import java.sql.Connection;
20
import java.sql.PreparedStatement;
21
import java.util.ArrayList;
22
import java.util.List;
23
import java.util.concurrent.Callable;
24
import java.util.concurrent.ExecutorService;
25
import java.util.concurrent.Executors;
26
import java.util.stream.Collectors;
27
import java.util.zip.GZIPInputStream;
28
import java.util.zip.ZipEntry;
29
import java.util.zip.ZipInputStream;
30

  
31
/**
32
 * External catalog service implementation
33
 */
34
@Service
35
@Transactional
36
@RequiredArgsConstructor
37
@Slf4j
38
public class ExternalCatalogServiceImpl implements IExternalCatalogService {
39
    /**
40
     * Buffer size
41
     */
42
    public static final int BUFFER_SIZE = 1024;
43
    /**
44
     * Directory where files for external directory will be stored
45
     */
46
    private static final String DIRECTORY_FOR_EXTERNAL_FILES = "sources";
47
    /**
48
     * URL for Pleiades file
49
     */
50
    private static final String PLEIADES_FILE_URL = "https://atlantides.org/downloads/pleiades/dumps/pleiades-names-latest.csv.gz";
51
    /**
52
     * Name of Pleiades file
53
     */
54
    private static final String PLEIADES_FILE_NAME = "pleiades-names-latest.csv";
55
    /**
56
     * URL for Pleiades file – needs to be formatted (more sources)
57
     */
58
    private static final String GEONAMES_FILE_URL = "https://download.geonames.org/export/dump/%s.zip";
59
    /**
60
     * Name of GeoNames file – needs to be formatted (more sources)
61
     */
62
    private static final String GEONAMES_FILE_NAME = "%s.txt";
63
    /**
64
     * URL for CIGS file
65
     */
66
    private static final String CIGS_FILE_URL = "https://zenodo.org/record/5642899/files/CIGS_v1_4_20211101.csv";
67
    /**
68
     * Name of CIGS file
69
     */
70
    private static final String CIGS_FILE_NAME = "CIGS_v1_4_20211101.csv";
71
    /**
72
     * Batch size for saving items
73
     */
74
    private static final int BATCH_SIZE = 5000;
75

  
76
    /**
77
     * External catalog repository
78
     */
79
    private final ExternalCatalogRepository externalCatalogRepository;
80

  
81
    /**
82
     * Hikari data source
83
     */
84
    private final HikariDataSource hikariDataSource;
85

  
86

  
87
    @Override
88
    public void updateCatalog() {
89
        log.info("Updating external catalog");
90
        try {
91
            Files.createDirectories(Paths.get(DIRECTORY_FOR_EXTERNAL_FILES)); // creates directory if not exists
92
            FileUtils.cleanDirectory(new File(DIRECTORY_FOR_EXTERNAL_FILES)); // cleans the directory
93
            externalCatalogRepository.deleteAll(); // clears database – updated list will be stored later
94
            addPleiadesSource();
95
            addGeonamesSources();
96
            addCigsSources();
97
        } catch (IOException e) {
98
            e.printStackTrace();
99
        }
100
        log.info("External catalog updated");
101
    }
102

  
103
    /**
104
     * Downloads, extracts and reads Pleiades sources and saves them to database
105
     */
106
    private void addPleiadesSource() {
107
        List<ExternalCatalogItem> externalCatalogItems = new ArrayList<>();
108
        byte[] buffer = new byte[BUFFER_SIZE];
109
        File pleiadesFile = new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), PLEIADES_FILE_NAME);
110
        try (InputStream fileIn = new URL(PLEIADES_FILE_URL).openStream();
111
             GZIPInputStream gZIPInputStream = new GZIPInputStream(fileIn);
112
             FileOutputStream fileOutputStream = new FileOutputStream(pleiadesFile)) {
113

  
114
            int bytes_read;
115

  
116
            while ((bytes_read = gZIPInputStream.read(buffer)) > 0) {
117
                fileOutputStream.write(buffer, 0, bytes_read);
118
            }
119

  
120
            log.info("The Pleiades file was decompressed successfully");
121

  
122
        } catch (IOException ex) {
123
            ex.printStackTrace();
124
        }
125

  
126
        try (InputStream csvData = new FileInputStream(pleiadesFile)) {
127
            CSVParser parser = CSVParser.parse(csvData, StandardCharsets.UTF_8, CSVFormat.Builder.create(CSVFormat.DEFAULT)
128
                    .setHeader()
129
                    .setSkipHeaderRecord(true)
130
                    .build());
131
            for (CSVRecord csvRecord : parser) {
132
                externalCatalogItems.add(new ExternalCatalogItem(csvRecord.toList(), ExternalSource.PLEIADES));
133
            }
134

  
135
        } catch (IOException ex) {
136
            ex.printStackTrace();
137
        }
138
        saveAllWithThreads(externalCatalogItems);
139
    }
140

  
141
    /**
142
     * Downloads, extracts and reads GeoNames sources and saves them to database
143
     */
144
    private void addGeonamesSources() {
145
        byte[] buffer = new byte[BUFFER_SIZE];
146
        for (String countryCode : ExternalCatalogItem.COUNTRY_CODES.keySet()) {
147
            List<ExternalCatalogItem> externalCatalogItems = new ArrayList<>();
148
            // Downloads file from URL and extracts it
149
            String url = String.format(GEONAMES_FILE_URL, countryCode);
150
            try (ZipInputStream zis = new ZipInputStream(new URL(url).openStream())) {
151
                ZipEntry zipEntry = zis.getNextEntry();
152
                while (zipEntry != null) {
153
                    FileOutputStream fileOutputStream = new FileOutputStream(new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), zipEntry.getName()));
154
                    int bytes_read;
155
                    while ((bytes_read = zis.read(buffer)) > 0) {
156
                        fileOutputStream.write(buffer, 0, bytes_read);
157
                    }
158
                    zipEntry = zis.getNextEntry();
159
                    fileOutputStream.close();
160
                }
161
            } catch (IOException e) {
162
                e.printStackTrace();
163
            }
164

  
165
            log.info("The Geonames file with country code " + countryCode + " was decompressed successfully");
166

  
167
            // Reads file and adds catalog items to list
168
            File geoNamesFile = new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), String.format(GEONAMES_FILE_NAME, countryCode));
169
            try (BufferedReader reader = new BufferedReader(new FileReader(geoNamesFile))) {
170
                String line;
171
                while ((line = reader.readLine()) != null) {
172
                    externalCatalogItems.add(new ExternalCatalogItem(List.of(line.split("\t")), ExternalSource.GEONAMES));
173
                }
174
            } catch (IOException e) {
175
                e.printStackTrace();
176
            }
177
            saveAllWithThreads(externalCatalogItems);
178
        }
179
    }
180

  
181
    /**
182
     * Downloads and reads CIGS sources and saves them to database
183
     */
184
    private void addCigsSources() {
185
        List<ExternalCatalogItem> externalCatalogItems = new ArrayList<>();
186
        byte[] buffer = new byte[BUFFER_SIZE];
187
        File cigsFile = new File(new File(DIRECTORY_FOR_EXTERNAL_FILES), CIGS_FILE_NAME);
188

  
189
        try (InputStream inputStream = new URL(CIGS_FILE_URL).openStream();
190
             FileOutputStream fileOutputStream = new FileOutputStream(cigsFile)) {
191
            int bytes_read;
192

  
193
            while ((bytes_read = inputStream.read(buffer)) > 0) {
194

  
195
                fileOutputStream.write(buffer, 0, bytes_read);
196
            }
197
        } catch (IOException e) {
198
            e.printStackTrace();
199
        }
200

  
201
        log.info("The CIGS file was downloaded successfully");
202

  
203
        try (InputStream csvData = new FileInputStream(cigsFile)) {
204
            CSVParser parser = CSVParser.parse(csvData, StandardCharsets.UTF_8, CSVFormat.Builder.create(CSVFormat.DEFAULT)
205
                    .setHeader()
206
                    .setSkipHeaderRecord(true)
207
                    .build());
208
            for (CSVRecord csvRecord : parser) {
209
                externalCatalogItems.add(new ExternalCatalogItem(csvRecord.toList(), ExternalSource.CIGS));
210
            }
211
        } catch (IOException e) {
212
            e.printStackTrace();
213
        }
214
        saveAllWithThreads(externalCatalogItems);
215
    }
216

  
217
    /**
218
     * Creates list of lists of external catalog items divided by batch size
219
     *
220
     * @param externalCatalogItems list of external catalog items
221
     * @return divided list of lists of external catalog items
222
     */
223
    private List<List<ExternalCatalogItem>> createSublist(List<ExternalCatalogItem> externalCatalogItems) {
224
        List<List<ExternalCatalogItem>> listOfSubList = new ArrayList<>();
225
        for (int i = 0; i < externalCatalogItems.size(); i += BATCH_SIZE) {
226
            if (i + BATCH_SIZE <= externalCatalogItems.size()) {
227
                listOfSubList.add(externalCatalogItems.subList(i, i + BATCH_SIZE));
228
            } else {
229
                listOfSubList.add(externalCatalogItems.subList(i, externalCatalogItems.size()));
230
            }
231
        }
232
        return listOfSubList;
233
    }
234

  
235
    /**
236
     * Divides list of external catalog items to sublist, creates threads (for saving sublists in batch) and executes them
237
     *
238
     * @param externalCatalogItems list of external catalog items
239
     */
240
    private void saveAllWithThreads(List<ExternalCatalogItem> externalCatalogItems) {
241
        ExecutorService executorService = Executors.newFixedThreadPool(hikariDataSource.getMaximumPoolSize());
242
        List<List<ExternalCatalogItem>> subList = createSublist(externalCatalogItems);
243
        List<Callable<Void>> callables = subList.stream().map(sublist ->
244
                (Callable<Void>) () -> {
245
                    saveAllInBatch(sublist);
246
                    return null;
247
                }).collect(Collectors.toList());
248
        try {
249
            executorService.invokeAll(callables);
250
        } catch (InterruptedException e) {
251
            e.printStackTrace();
252
        }
253
    }
254

  
255
    /**
256
     * Saves external catalog items in batch
257
     *
258
     * @param externalCatalogItems list of external catalog items
259
     */
260
    private void saveAllInBatch(List<ExternalCatalogItem> externalCatalogItems) {
261
        String sql = String.format("INSERT INTO %s (id, external_source, latitude, longitude, location_precision, max_date, " +
262
                "min_date, time_period_keys, pid, names, feature_code, country, accuracy, geoname_id, pleiades_id, osm_id) " +
263
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", ExternalCatalogItem.class.getAnnotation(Table.class).name());
264
        try (Connection connection = hikariDataSource.getConnection();
265
             PreparedStatement statement = connection.prepareStatement(sql)) {
266
            int counter = 0;
267
            for (ExternalCatalogItem item : externalCatalogItems) {
268
                statement.clearParameters();
269
                statement.setObject(1, item.getId());
270
                statement.setString(2, item.getExternalSource().name());
271
                statement.setObject(3, item.getLatitude());
272
                statement.setObject(4, item.getLongitude());
273
                statement.setString(5, item.getLocationPrecision());
274
                statement.setObject(6, item.getMaxDate());
275
                statement.setObject(7, item.getMinDate());
276
                statement.setString(8, item.getTimePeriodKeys());
277
                statement.setString(9, item.getPid());
278
                statement.setString(10, String.join(",", item.getNames()));
279
                statement.setString(11, item.getFeatureCode());
280
                statement.setString(12, item.getCountry());
281
                statement.setObject(13, item.getAccuracy());
282
                statement.setObject(14, item.getGeonameId());
283
                statement.setObject(15, item.getPleiadesId());
284
                statement.setObject(16, item.getOsmId());
285
                statement.addBatch();
286
                counter++;
287
                if (counter % BATCH_SIZE == 0 || counter == externalCatalogItems.size()) {
288
                    statement.executeBatch();
289
                    statement.clearBatch();
290
                }
291
            }
292
        } catch (Exception e) {
293
            e.printStackTrace();
294
        }
295
    }
296
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/IExternalCatalogItemService.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import java.util.List;
4

  
5
/**
6
 * External catalog service interface
7
 */
8
public interface IExternalCatalogItemService {
9
    /**
10
     * Updates external catalog
11
     */
12
    void updateCatalog();
13

  
14
    /**
15
     * Returns external catalog items satisfying given filter
16
     *
17
     * @param name name
18
     * @return list of external catalog items satisfying given filter
19
     */
20
    List<ExternalCatalogItem> getCatalog(String name, ExternalSource source);
21
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/IExternalCatalogService.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
/**
4
 * External catalog service interface
5
 */
6
public interface IExternalCatalogService {
7
    /**
8
     * Updates external catalog
9
     */
10
    void updateCatalog();
11
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/SetToStringConverter.java
1 1
package cz.zcu.kiv.backendapi.external;
2 2

  
3
import org.springframework.stereotype.Component;
4

  
3 5
import javax.persistence.AttributeConverter;
4 6
import java.util.Arrays;
5 7
import java.util.HashSet;
......
9 11
/**
10 12
 * Class that converts set of strings to string and string to set of strings
11 13
 */
14
@Component
12 15
public class SetToStringConverter implements AttributeConverter<Set<String>, String> {
13 16
    /**
14 17
     * Delimiter for splitting/joining string
backend/src/main/java/cz/zcu/kiv/backendapi/path/PathController.java
1 1
package cz.zcu.kiv.backendapi.path;
2 2

  
3 3
import cz.zcu.kiv.backendapi.catalog.ICatalogItemService;
4
import io.swagger.v3.oas.annotations.Operation;
4 5
import lombok.RequiredArgsConstructor;
5 6
import org.springframework.web.bind.annotation.GetMapping;
6 7
import org.springframework.web.bind.annotation.RequestBody;
......
27 28
     * @return path DTO with highlighted text and found catalog items
28 29
     */
29 30
    @GetMapping("")
31
    @Operation(summary = "returns path with highlighted text and found catalog items based on given text")
30 32
    public PathDto getPath(@RequestBody PathDto pathDto) {
31 33
        return catalogItemService.getPath(pathDto.getText());
32 34
    }
backend/src/main/java/cz/zcu/kiv/backendapi/security/SecurityConfig.java
62 62
        PERMITTED_ENDPOINTS.put("/v3/api-docs/swagger-config", HttpMethod.GET);
63 63
        PERMITTED_ENDPOINTS.put("/catalog-items", HttpMethod.GET);
64 64
        PERMITTED_ENDPOINTS.put("/catalog-items/**", HttpMethod.GET);
65
        PERMITTED_ENDPOINTS.put("/external-catalog-items", HttpMethod.POST); //TODO delete
65
        PERMITTED_ENDPOINTS.put("/title-page", HttpMethod.GET);
66 66
    }
67 67

  
68 68
    /**
......
84 84
                .authorizeRequests()
85 85
                .antMatchers(HttpMethod.GET, PERMITTED_ENDPOINTS.keySet().stream().filter(k -> PERMITTED_ENDPOINTS.get(k).equals(HttpMethod.GET)).toArray(String[]::new)).permitAll()
86 86
                .antMatchers(HttpMethod.POST, "/login").permitAll()
87
                .antMatchers(HttpMethod.POST, "/external-catalog-items").permitAll() //TODO delete
87
                .antMatchers("/external-catalog-items").hasRole(Role.ADMIN.name())
88 88
                .antMatchers(HttpMethod.PATCH, "/users/*/permissions", "/users/*/password").hasRole(Role.ADMIN.name())
89 89
                .antMatchers(HttpMethod.DELETE, "/users/**").hasRole(Role.ADMIN.name())
90 90
                .antMatchers(HttpMethod.GET, "/users").hasRole(Role.ADMIN.name())
backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest.java
88 88
        // given
89 89
        CatalogItemDto catalogItemDto = new CatalogItemDto();
90 90
        catalogItemDto.setName("name");
91
        catalogItemDto.setBibliography(Set.of("bibl"));
92
        catalogItemDto.setTypes(Set.of("type"));
93
        catalogItemDto.setAlternativeNames(Set.of("altName"));
94
        catalogItemDto.setCountries(Set.of("country"));
95
        catalogItemDto.setWrittenForms(Set.of("written"));
91
        catalogItemDto.setBibliography(Stream.of("bibl").collect(Collectors.toSet()));
92
        catalogItemDto.setTypes(Stream.of("type").collect(Collectors.toSet()));
93
        catalogItemDto.setAlternativeNames(Stream.of("altName").collect(Collectors.toSet()));
94
        catalogItemDto.setCountries(Stream.of("country").collect(Collectors.toSet()));
95
        catalogItemDto.setWrittenForms(Stream.of("written").collect(Collectors.toSet()));
96 96
        catalogItemDto.setCertainty(0);
97 97
        catalogItemDto.setLatitude(0.1);
98 98
        catalogItemDto.setLongitude(0.2);
......
102 102

  
103 103
        CatalogItem catalogItem = new CatalogItem();
104 104
        catalogItem.setName("name");
105
        catalogItem.setBibliography(Set.of(new Bibliography("bibl", catalogItem)));
106
        catalogItem.setTypes(Set.of(type));
107
        catalogItem.setAlternativeNames(Set.of(new AlternativeName("altName", catalogItem)));
108
        catalogItem.setCountries(Set.of(new Country("country", catalogItem)));
109
        catalogItem.setWrittenForms(Set.of(new WrittenForm("written", catalogItem)));
105
        catalogItem.setBibliography(Stream.of(new Bibliography("bibl", catalogItem)).collect(Collectors.toSet()));
106
        catalogItem.setTypes(Stream.of(type).collect(Collectors.toSet()));
107
        catalogItem.setAlternativeNames(Stream.of(new AlternativeName("altName", catalogItem), new AlternativeName("name", catalogItem)).collect(Collectors.toSet()));
108
        catalogItem.setCountries(Stream.of(new Country("country", catalogItem)).collect(Collectors.toSet()));
109
        catalogItem.setWrittenForms(Stream.of(new WrittenForm("written", catalogItem)).collect(Collectors.toSet()));
110 110
        catalogItem.setCertainty(0);
111 111
        catalogItem.setLatitude(0.1);
112 112
        catalogItem.setLongitude(0.2);
......
177 177

  
178 178
        CatalogItemDto catalogItemDto = new CatalogItemDto();
179 179
        catalogItemDto.setName("name");
180
        catalogItemDto.setBibliography(Set.of("bibl"));
181
        catalogItemDto.setTypes(Set.of("type"));
182
        catalogItemDto.setAlternativeNames(Set.of("altName"));
183
        catalogItemDto.setCountries(Set.of("country"));
184
        catalogItemDto.setWrittenForms(Set.of("written"));
180
        catalogItemDto.setBibliography(Stream.of("bibl").collect(Collectors.toSet()));
181
        catalogItemDto.setTypes(Stream.of("type").collect(Collectors.toSet()));
182
        catalogItemDto.setAlternativeNames(Stream.of("altName").collect(Collectors.toSet()));
183
        catalogItemDto.setCountries(Stream.of("country").collect(Collectors.toSet()));
184
        catalogItemDto.setWrittenForms(Stream.of("written").collect(Collectors.toSet()));
185 185
        catalogItemDto.setCertainty(0);
186 186
        catalogItemDto.setLatitude(0.1);
187 187
        catalogItemDto.setLongitude(0.2);
......
237 237
        assertThat(capturedCatalogItem.getLongitude()).isEqualTo(catalogItem.getLongitude());
238 238
        assertThat(capturedCatalogItem.getDescription()).isEqualTo(catalogItem.getDescription());
239 239
        assertThat(capturedCatalogItem.getTypes().stream().map(Type::getType).collect(Collectors.toSet())).isEqualTo(catalogItem.getTypes().stream().map(Type::getType).collect(Collectors.toSet()));
240
        assertThat(capturedCatalogItem.getAlternativeNames().stream().map(AlternativeName::getName).collect(Collectors.toSet())).isEqualTo(catalogItem.getAlternativeNames().stream().map(AlternativeName::getName).collect(Collectors.toSet()));
240
        Set<String> alternativeNamesEntity = catalogItem.getAlternativeNames().stream().map(AlternativeName::getName).collect(Collectors.toSet());
241
        alternativeNamesEntity.add(catalogItem.getName());
242
        assertThat(capturedCatalogItem.getAlternativeNames().stream().map(AlternativeName::getName).collect(Collectors.toSet())).isEqualTo(alternativeNamesEntity);
241 243
        assertThat(capturedCatalogItem.getCountries().stream().map(Country::getName).collect(Collectors.toSet())).isEqualTo(catalogItem.getCountries().stream().map(Country::getName).collect(Collectors.toSet()));
242 244
        assertThat(capturedCatalogItem.getBibliography().stream().map(Bibliography::getSource).collect(Collectors.toSet())).isEqualTo(catalogItem.getBibliography().stream().map(Bibliography::getSource).collect(Collectors.toSet()));
243 245
        assertThat(capturedCatalogItem.getWrittenForms().stream().map(WrittenForm::getForm).collect(Collectors.toSet())).isEqualTo(catalogItem.getWrittenForms().stream().map(WrittenForm::getForm).collect(Collectors.toSet()));
backend/src/test/java/cz/zcu/kiv/backendapi/external/ExternalCatalogItemItemServiceImplTest.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import com.zaxxer.hikari.HikariDataSource;
4
import org.junit.jupiter.api.BeforeEach;
5
import org.junit.jupiter.api.Test;
6
import org.junit.jupiter.api.extension.ExtendWith;
7
import org.mockito.Mock;
8
import org.mockito.junit.jupiter.MockitoExtension;
9

  
10
import java.util.List;
11
import java.util.Set;
12
import java.util.UUID;
13

  
14
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
15
import static org.junit.jupiter.api.Assertions.assertTrue;
16
import static org.mockito.BDDMockito.given;
17
import static org.mockito.Mockito.verify;
18

  
19
@ExtendWith(MockitoExtension.class)
20
class ExternalCatalogItemItemServiceImplTest {
21

  
22
    @Mock
23
    private ExternalCatalogItemRepository externalCatalogItemRepository;
24

  
25
    @Mock
26
    private HikariDataSource hikariDataSource;
27

  
28
    @Mock
29
    private SetToStringConverter setToStringConverter;
30

  
31
    private ExternalCatalogItemItemServiceImpl underTest;
32

  
33
    @BeforeEach
34
    void setUp() {
35
        underTest = new ExternalCatalogItemItemServiceImpl(externalCatalogItemRepository, hikariDataSource, setToStringConverter);
36
    }
37

  
38
    @Test
39
    void getCatalog() {
40
        // given
41
        ExternalCatalogItem catalogItem1 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.PLEIADES, 10.0, 10.0, null, null, null, null, null, Set.of("first", "NAME"), null, null, null, null, null, null);
42
        ExternalCatalogItem catalogItem2 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.PLEIADES, 10.0, 10.0, null, null, null, null, null, Set.of("second", "name"), null, null, null, null, null, null);
43
        ExternalCatalogItem catalogItem3 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.PLEIADES, 10.0, 10.0, null, null, null, null, null, Set.of("fourth", "nane"), null, null, null, null, null, null);
44
        String name = "na?*";
45
        ExternalSource source = ExternalSource.PLEIADES;
46
        given(externalCatalogItemRepository.getFilteredExternalCatalog("%na_%%", source.name())).willReturn(List.of(catalogItem1, catalogItem2, catalogItem3));
47

  
48
        // when
49
        List<ExternalCatalogItem> result = underTest.getCatalog(name, source);
50

  
51
        // then
52
        verify(externalCatalogItemRepository).getFilteredExternalCatalog("%na_%%", source.name());
53
        assertThat(result.size()).isEqualTo(3);
54
        assertTrue(result.contains(catalogItem1));
55
        assertTrue(result.contains(catalogItem2));
56
        assertTrue(result.contains(catalogItem3));
57
    }
58
}
backend/src/test/java/cz/zcu/kiv/backendapi/external/ExternalCatalogItemRepositoryTest.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import org.junit.jupiter.api.AfterEach;
4
import org.junit.jupiter.api.BeforeEach;
5
import org.junit.jupiter.api.Test;
6
import org.springframework.beans.factory.annotation.Autowired;
7
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
8

  
9
import java.util.List;
10
import java.util.Set;
11
import java.util.UUID;
12

  
13
import static org.assertj.core.api.Assertions.assertThat;
14
import static org.junit.jupiter.api.Assertions.assertTrue;
15

  
16
@DataJpaTest
17
class ExternalCatalogItemRepositoryTest {
18

  
19
    @Autowired
20
    private ExternalCatalogItemRepository underTest;
21

  
22
    private ExternalCatalogItem catalogItem1;
23
    private ExternalCatalogItem catalogItem2;
24
    private ExternalCatalogItem catalogItem3;
25
    private ExternalCatalogItem catalogItem4;
26

  
27
    private ExternalCatalogItem catalogItem5;
28
    private ExternalCatalogItem catalogItem6;
29

  
30
    private ExternalCatalogItem catalogItem7;
31

  
32
    @BeforeEach
33
    void setUp() {
34
        catalogItem1 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.PLEIADES, 10.0, 10.0, null, null, null, null, null, Set.of("first", "NAME"), null, null, null, null, null, null);
35
        catalogItem2 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.PLEIADES, 10.0, 10.0, null, null, null, null, null, Set.of("second", "name"), null, null, null, null, null, null);
36
        catalogItem3 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.CIGS, 10.0, 10.0, null, null, null, null, null, Set.of("third", "NAME"), null, null, null, null, null, null);
37
        catalogItem4 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.PLEIADES, 10.0, 10.0, null, null, null, null, null, Set.of("fourth", "nane"), null, null, null, null, null, null);
38
        catalogItem5 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.GEONAMES, 10.0, 10.0, null, null, null, null, null, Set.of("fifthName", "Achala"), null, null, null, null, null, null);
39
        catalogItem6 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.GEONAMES, 10.0, 10.0, null, null, null, null, null, Set.of("fifthMama", "Bafala"), null, null, null, null, null, null);
40
        catalogItem7 = new ExternalCatalogItem(UUID.randomUUID(), ExternalSource.CIGS, 10.0, 10.0, null, null, null, null, null, Set.of("seventhName", "hello"), null, null, null, null, null, null);
41
        underTest.saveAll(List.of(catalogItem1, catalogItem2, catalogItem3, catalogItem4, catalogItem5, catalogItem6, catalogItem7));
42
    }
43

  
44
    @AfterEach
45
    void tearDown() {
46
        underTest.deleteAll();
47
    }
48

  
49
    @Test
50
    void getFilteredExternalCatalog() {
51
        // given
52
        // when
53
        List<ExternalCatalogItem> result = underTest.getFilteredExternalCatalog("%name%", ExternalSource.PLEIADES.name());
54

  
55
        // then
56
        assertThat(result.size()).isEqualTo(2);
57
        assertTrue(result.contains(catalogItem1));
58
        assertTrue(result.contains(catalogItem2));
59
    }
60

  
61
    @Test
62
    void getFilteredExternalCatalogWildcardsCharacter() {
63
        // given
64
        // when
65
        List<ExternalCatalogItem> result = underTest.getFilteredExternalCatalog("%na_e%", ExternalSource.PLEIADES.name());
66

  
67
        // then
68
        assertThat(result.size()).isEqualTo(3);
69
        assertTrue(result.contains(catalogItem1));
70
        assertTrue(result.contains(catalogItem2));
71
        assertTrue(result.contains(catalogItem4));
72
    }
73

  
74
    @Test
75
    void getFilteredExternalCatalogWildcardsCharacters() {
76
        // given
77
        // when
78
        List<ExternalCatalogItem> result = underTest.getFilteredExternalCatalog("%fifth%%", ExternalSource.GEONAMES.name());
79

  
80
        // then
81
        assertThat(result.size()).isEqualTo(2);
82
        assertTrue(result.contains(catalogItem5));
83
        assertTrue(result.contains(catalogItem6));
84
    }
85

  
86
    @Test
87
    void getFilteredExternalCatalogAllSource() {
88
        // given
89
        // when
90
        List<ExternalCatalogItem> result = underTest.getFilteredExternalCatalog("%%%", ExternalSource.CIGS.name());
91

  
92
        // then
93
        assertThat(result.size()).isEqualTo(2);
94
        assertTrue(result.contains(catalogItem3));
95
        assertTrue(result.contains(catalogItem7));
96
    }
97
}

Také k dispozici: Unified diff