Projekt

Obecné

Profil

« Předchozí | Další » 

Revize e21b7441

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

Added loading of external catalog items

re #9624

Zobrazit rozdíly:

backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItem.java
115 115
    )
116 116
    private Set<Type> types = new HashSet<>();
117 117

  
118
    public CatalogItem(final List<String> csvFields) {
118
    public CatalogItem(List<String> csvFields) {
119 119

  
120 120
        this.name = csvFields.get(1);
121 121
        Set<String> stringList = processListField(csvFields.get(2));
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogItemService.java
6 6
import java.util.UUID;
7 7

  
8 8
/**
9
 * Catalog service interface
9
 * Catalog item service interface
10 10
 */
11 11
public interface ICatalogItemService {
12 12
    /**
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogController.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
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;
7

  
8
/**
9
 * Controller for external catalog
10
 */
11
@RestController
12
@RequiredArgsConstructor
13
@RequestMapping("/external-catalog-items")
14
public class ExternalCatalogController {
15

  
16
    /**
17
     * External catalog service
18
     */
19
    private final IExternalCatalogService externalCatalogService;
20

  
21
    @PostMapping("")
22
    public void updateCatalog() {
23
        externalCatalogService.updateCatalog();
24
    }
25
}
backend/src/main/java/cz/zcu/kiv/backendapi/external/ExternalCatalogItem.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
import lombok.EqualsAndHashCode;
4
import lombok.Getter;
5
import lombok.NoArgsConstructor;
6
import lombok.Setter;
7

  
8
import javax.persistence.*;
9
import java.util.*;
10
import java.util.regex.Matcher;
11
import java.util.regex.Pattern;
12
import java.util.stream.Collectors;
13

  
14
/**
15
 * Class representing external catalog items
16
 */
17
@Getter
18
@Setter
19
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
20
@NoArgsConstructor
21
@Entity
22
@Table(name = "external_catalog_items")
23
public class ExternalCatalogItem {
24
    /**
25
     * Map where key is country code and value is name of country
26
     */
27
    protected static final Map<String, String> COUNTRY_CODES;
28

  
29
    /**
30
     * Integer pattern for finding int value in string
31
     */
32
    private static final Pattern INTEGER_PATTERN = Pattern.compile("\\d+");
33

  
34
    /**
35
     * Double pattern for finding double value in string
36
     */
37
    private static final Pattern DOUBLE_PATTERN = Pattern.compile("(\\d+[.]\\d+)|(\\d+)");
38

  
39
    static {
40
        COUNTRY_CODES = new LinkedHashMap<>();
41
        COUNTRY_CODES.put("IQ", "Iraq");
42
        COUNTRY_CODES.put("IR", "Iran");
43
        COUNTRY_CODES.put("SY", "Syria");
44
        COUNTRY_CODES.put("TR", "Turkey");
45
        COUNTRY_CODES.put("JO", "Jordan");
46
        COUNTRY_CODES.put("LB", "Lebanon");
47
        COUNTRY_CODES.put("IL", "Israel");
48
        COUNTRY_CODES.put("PS", "Palestine");
49
        COUNTRY_CODES.put("CY", "Cyprus");
50
        COUNTRY_CODES.put("EG", "Egypt");
51
        COUNTRY_CODES.put("SD", "Sudan");
52
        COUNTRY_CODES.put("BH", "Bahrain");
53
        COUNTRY_CODES.put("KW", "Kuwait");
54
        COUNTRY_CODES.put("OM", "Oman");
55
        COUNTRY_CODES.put("SA", "Saudi Arabia");
56
        COUNTRY_CODES.put("AE", "United Arab Emirates");
57
        COUNTRY_CODES.put("YE", "Yemen");
58
        COUNTRY_CODES.put("AF", "Afghanistan");
59
        COUNTRY_CODES.put("AM", "Armenia");
60
        COUNTRY_CODES.put("GE", "Georgia");
61
    }
62

  
63
    /**
64
     * Id
65
     */
66
    @Id
67
    @EqualsAndHashCode.Include
68
    UUID id = UUID.randomUUID();
69

  
70
    /**
71
     * External source
72
     */
73
    @Enumerated(EnumType.STRING)
74
    private ExternalSource externalSource;
75

  
76
    /**
77
     * Latitude
78
     */
79
    private Double latitude;
80

  
81
    /**
82
     * Longitude
83
     */
84
    private Double longitude;
85

  
86
    /**
87
     * Precision of location
88
     */
89
    private String locationPrecision;
90

  
91
    /**
92
     * Max date
93
     */
94
    private Integer maxDate;
95

  
96
    /**
97
     * Min date
98
     */
99
    private Integer minDate;
100

  
101
    /**
102
     * Keys for time periods
103
     */
104
    @Column(length = 1000)
105
    private String timePeriodKeys;
106

  
107
    /**
108
     * Pid
109
     */
110
    private String pid;
111

  
112
    /**
113
     * Set of names
114
     */
115
    @Convert(converter = SetToStringConverter.class)
116
    @Column(length = 20000)
117
    private Set<String> names = new HashSet<>();
118

  
119
    /**
120
     * Feature code
121
     */
122
    private String featureCode;
123

  
124
    /**
125
     * Country
126
     */
127
    private String country;
128

  
129
    /**
130
     * Accuracy
131
     */
132
    private Integer accuracy;
133

  
134
    /**
135
     * GeoName ID
136
     */
137
    private Long geonameId;
138

  
139
    /**
140
     * Pleiades ID
141
     */
142
    private Long pleiadesId;
143

  
144
    /**
145
     * Osm ID
146
     */
147
    private Long osmId;
148

  
149
    /**
150
     * Creates new external catalog item from list of string containing information and catalog source type
151
     *
152
     * @param fieldList      list of string containing information about the catalog item
153
     * @param externalSource external source type
154
     */
155
    public ExternalCatalogItem(List<String> fieldList, ExternalSource externalSource) {
156
        this.externalSource = externalSource;
157
        if (externalSource == ExternalSource.PLEIADES) {
158
            this.locationPrecision = fieldList.get(8);
159
            this.maxDate = processIntField(fieldList.get(9));
160
            this.minDate = processIntField(fieldList.get(10));
161
            this.pid = fieldList.get(16);
162
            this.latitude = processDoubleField(fieldList.get(17));
163
            this.longitude = processDoubleField(fieldList.get(18));
164
            this.timePeriodKeys = fieldList.get(22);
165
            this.names.add(fieldList.get(24));
166
            this.names.addAll(processListField(fieldList.get(12)));
167
            this.names.addAll(processListField(fieldList.get(14)));
168
        } else if (externalSource == ExternalSource.GEONAMES) {
169
            this.geonameId = processLongField(fieldList.get(0));
170
            this.names.add(fieldList.get(1));
171
            this.names.add(fieldList.get(2));
172
            this.names.addAll(processListField(fieldList.get(3)));
173
            this.latitude = processDoubleField(fieldList.get(4));
174
            this.longitude = processDoubleField(fieldList.get(5));
175
            this.featureCode = fieldList.get(7);
176
            this.country = convertCountryCode(fieldList.get(8));
177
        } else if (externalSource == ExternalSource.CIGS) {
178
            this.accuracy = processIntField(fieldList.get(1));
179
            this.names.add(fieldList.get(3));
180
            this.names.add(fieldList.get(4));
181
            this.names.add(fieldList.get(5));
182
            this.names.add(fieldList.get(6));
183
            this.names.add(fieldList.get(7));
184
            this.names.add(fieldList.get(8));
185
            this.names.add(fieldList.get(9));
186
            this.names.add(fieldList.get(10));
187
            this.names.add(fieldList.get(11));
188
            this.pleiadesId = processLongField(fieldList.get(12));
189
            this.osmId = processLongField(fieldList.get(13));
190
            this.geonameId = processLongField(fieldList.get(15));
191
            this.longitude = processDoubleField(fieldList.get(23));
192
            this.latitude = processDoubleField(fieldList.get(24));
193
        }
194
    }
195

  
196
    /**
197
     * Converts country code to country name
198
     *
199
     * @param countryCode country code
200
     * @return country name
201
     */
202
    private String convertCountryCode(String countryCode) {
203
        if (COUNTRY_CODES.containsKey(countryCode)) {
204
            return COUNTRY_CODES.get(countryCode);
205
        }
206
        return countryCode;
207
    }
208

  
209
    /**
210
     * Processes field of type long
211
     *
212
     * @param field field
213
     * @return long if long found in field, null otherwise
214
     */
215
    private Long processLongField(String field) {
216
        Matcher matcher = INTEGER_PATTERN.matcher(field);
217
        if (matcher.find()) {
218
            return Long.parseLong(matcher.group());
219
        } else {
220
            return null;
221
        }
222
    }
223

  
224
    /**
225
     * Processes field of type int
226
     *
227
     * @param field field
228
     * @return int if int found in field, null otherwise
229
     */
230
    private Integer processIntField(String field) {
231
        Matcher matcher = INTEGER_PATTERN.matcher(field);
232
        if (matcher.find()) {
233
            return Integer.parseInt(matcher.group());
234
        } else {
235
            return null;
236
        }
237
    }
238

  
239
    /**
240
     * Processes field of type double
241
     *
242
     * @param field field
243
     * @return double if double found in field, null otherwise
244
     */
245
    private Double processDoubleField(String field) {
246
        Matcher matcher = DOUBLE_PATTERN.matcher(field);
247
        if (matcher.find()) {
248
            return Double.parseDouble(matcher.group());
249
        } else {
250
            return null;
251
        }
252
    }
253

  
254
    /**
255
     * Processes list field
256
     *
257
     * @param field list field (string seperated by commas)
258
     * @return set from list field
259
     */
260
    private Set<String> processListField(String field) {
261
        if (field.isEmpty()) {
262
            return new HashSet<>();
263
        }
264
        return Arrays.stream(field.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toSet());
265
    }
266
}
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/ExternalSource.java
1
package cz.zcu.kiv.backendapi.external;
2

  
3
/**
4
 * Enum representing different sources of external catalog items
5
 */
6
public enum ExternalSource {
7
    PLEIADES,
8
    GEONAMES,
9
    CIGS
10
}
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
package cz.zcu.kiv.backendapi.external;
2

  
3
import javax.persistence.AttributeConverter;
4
import java.util.Arrays;
5
import java.util.HashSet;
6
import java.util.Set;
7
import java.util.stream.Collectors;
8

  
9
/**
10
 * Class that converts set of strings to string and string to set of strings
11
 */
12
public class SetToStringConverter implements AttributeConverter<Set<String>, String> {
13
    /**
14
     * Delimiter for splitting/joining string
15
     */
16
    private static final String DELIMITER = ",";
17

  
18
    @Override
19
    public String convertToDatabaseColumn(Set<String> attribute) {
20
        return attribute == null ? null : String.join(DELIMITER, attribute);
21
    }
22

  
23
    @Override
24
    public Set<String> convertToEntityAttribute(String dbData) {
25
        return dbData == null ? new HashSet<>() : Arrays.stream(dbData.split(DELIMITER)).collect(Collectors.toSet());
26
    }
27

  
28
}
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 66
    }
66 67

  
67 68
    /**
......
83 84
                .authorizeRequests()
84 85
                .antMatchers(HttpMethod.GET, PERMITTED_ENDPOINTS.keySet().stream().filter(k -> PERMITTED_ENDPOINTS.get(k).equals(HttpMethod.GET)).toArray(String[]::new)).permitAll()
85 86
                .antMatchers(HttpMethod.POST, "/login").permitAll()
87
                .antMatchers(HttpMethod.POST, "/external-catalog-items").permitAll() //TODO delete
86 88
                .antMatchers(HttpMethod.PATCH, "/users/*/permissions", "/users/*/password").hasRole(Role.ADMIN.name())
87 89
                .antMatchers(HttpMethod.DELETE, "/users/**").hasRole(Role.ADMIN.name())
88 90
                .antMatchers(HttpMethod.GET, "/users").hasRole(Role.ADMIN.name())

Také k dispozici: Unified diff