Projekt

Obecné

Profil

Stáhnout (12.9 KB) Statistiky
| Větev: | Tag: | Revize:
1
package cz.zcu.kiv.backendapi.catalog;
2

    
3
import cz.zcu.kiv.backendapi.alternativename.CatalogItemName;
4
import cz.zcu.kiv.backendapi.bibliography.Bibliography;
5
import cz.zcu.kiv.backendapi.country.Country;
6
import cz.zcu.kiv.backendapi.exception.ApiRequestException;
7
import cz.zcu.kiv.backendapi.path.PathDto;
8
import cz.zcu.kiv.backendapi.type.ITypeService;
9
import cz.zcu.kiv.backendapi.type.Type;
10
import cz.zcu.kiv.backendapi.writtenform.WrittenForm;
11
import lombok.RequiredArgsConstructor;
12
import lombok.extern.slf4j.Slf4j;
13
import org.apache.commons.lang3.StringUtils;
14
import org.springframework.http.HttpStatus;
15
import org.springframework.stereotype.Service;
16
import org.springframework.transaction.annotation.Transactional;
17

    
18
import java.util.*;
19
import java.util.concurrent.atomic.AtomicInteger;
20
import java.util.function.Predicate;
21
import java.util.regex.Matcher;
22
import java.util.regex.Pattern;
23
import java.util.stream.Collectors;
24

    
25
/**
26
 * Catalog item service implementation
27
 */
28
@Service
29
@Transactional
30
@RequiredArgsConstructor
31
@Slf4j
32
public class CatalogItemServiceImpl implements ICatalogItemService {
33
    /**
34
     * Regex for one arbitrary character in string
35
     */
36
    private static final String WILDCARD_CHARACTER_REGEX = "\\?";
37

    
38
    /**
39
     * Regex for one arbitrary character in string used in Java
40
     */
41
    private static final String WILDCARD_CHARACTER_REGEX_JAVA = ".";
42

    
43
    /**
44
     * Regex for any number of arbitrary characters in string
45
     */
46
    private static final String WILDCARD_CHARACTERS_REGEX = "\\*";
47

    
48
    /**
49
     * Regex for any number of arbitrary characters in string used in Java
50
     */
51
    private static final String WILDCARD_CHARACTERS_REGEX_JAVA = ".*";
52

    
53
    /**
54
     * Regex for finding punctuation at the start of word
55
     */
56
    private static final String START_PUNCTUATION_REGEX = "^[\\p{Punct}\\p{IsPunctuation}]+";
57

    
58
    /**
59
     * Regex for finding punctuation at the end of word
60
     */
61
    private static final String END_PUNCTUATION_REGEX = "[\\p{Punct}\\p{IsPunctuation}]+$";
62

    
63
    /**
64
     * Pattern for finding punctuation at the start of word
65
     */
66
    private static final Pattern START_PUNCTUATION_PATTERN = Pattern.compile(START_PUNCTUATION_REGEX);
67

    
68
    /**
69
     * Pattern for finding punctuation at the end of word
70
     */
71
    private static final Pattern END_PUNCTUATION_PATTERN = Pattern.compile(END_PUNCTUATION_REGEX);
72

    
73
    /**
74
     * Message for exception when catalog item is not found by id
75
     */
76
    private static final String CATALOG_ITEM_NOT_FOUND = "Catalog item not found";
77

    
78

    
79
    /**
80
     * Catalog repository
81
     */
82
    private final CatalogItemRepository catalogItemRepository;
83

    
84
    /**
85
     * Type service
86
     */
87
    private final ITypeService typeService;
88

    
89
    @Override
90
    public void saveCatalog(List<CatalogItem> catalogItems) {
91
        log.info("Saving catalog");
92
        catalogItems.forEach(this::saveCatalogEntity);
93
    }
94

    
95
    @Override
96
    public void saveCatalogItem(CatalogItemDto catalogItemDto) {
97
        log.info("Saving catalog item");
98
        CatalogItem catalogItem = new CatalogItem();
99
        convertDtoToEntity(catalogItemDto, catalogItem);
100
        saveCatalogEntity(catalogItem);
101
    }
102

    
103
    @Override
104
    public void updateCatalogItem(UUID id, CatalogItemDto catalogItemDto) {
105
        CatalogItem catalogItem = catalogItemRepository.findById(id).orElseThrow(() -> {
106
            log.error(CATALOG_ITEM_NOT_FOUND);
107
            throw new ApiRequestException(CATALOG_ITEM_NOT_FOUND, HttpStatus.NOT_FOUND);
108
        });
109
        convertDtoToEntity(catalogItemDto, catalogItem);
110
        saveCatalogEntity(catalogItem);
111
        log.info("Catalog item updated");
112
    }
113

    
114
    @Override
115
    public void deleteCatalogItem(UUID id) {
116
        if (!catalogItemRepository.existsById(id)) {
117
            log.error(CATALOG_ITEM_NOT_FOUND);
118
            throw new ApiRequestException(CATALOG_ITEM_NOT_FOUND, HttpStatus.NOT_FOUND);
119
        }
120
        catalogItemRepository.deleteById(id);
121
        log.info("Catalog item deleted");
122
    }
123

    
124
    @Override
125
    public CatalogItemDto getCatalogItem(UUID id) {
126
        CatalogItem catalogItem = catalogItemRepository.findById(id).orElseThrow(() -> {
127
            log.error(CATALOG_ITEM_NOT_FOUND);
128
            throw new ApiRequestException(CATALOG_ITEM_NOT_FOUND, HttpStatus.NOT_FOUND);
129
        });
130

    
131
        return convertEntityToDto(catalogItem);
132
    }
133

    
134
    @Override
135
    public PathDto getPath(String text) {
136
        PathDto pathDto = new PathDto();
137
        StringBuilder highlightedText = new StringBuilder();
138
        List<List<CatalogItemDto>> foundCatalogItems = new ArrayList<>();
139

    
140
        Set<String> types = typeService.getAllTypesAsString();
141

    
142
        String[] tokens = text.split("((?<=\\s)|(?=\\s+))");
143
        for (String token : tokens) {
144
            if (StringUtils.isBlank(token)) {
145
                highlightedText.append(token);
146
                continue;
147
            }
148
            Matcher matcherStart = START_PUNCTUATION_PATTERN.matcher(token);
149
            Matcher matcherEnd = END_PUNCTUATION_PATTERN.matcher(token);
150
            String prefix = "";
151
            String suffix = "";
152
            String textToFind;
153
            int startTextIndex = 0;
154
            int endTextIndex = token.length();
155

    
156
            if (matcherStart.find()) {
157
                int start = matcherStart.start();
158
                startTextIndex = matcherStart.end();
159
                prefix = token.substring(start, startTextIndex);
160
            }
161
            if (matcherEnd.find()) {
162
                endTextIndex = matcherEnd.start();
163
                int end = matcherEnd.end();
164
                suffix = token.substring(endTextIndex, end);
165
            }
166

    
167
            if (endTextIndex < startTextIndex) {
168
                highlightedText.append(prefix);
169
                continue;
170
            }
171

    
172
            textToFind = token.substring(startTextIndex, endTextIndex);
173

    
174
            if (types.contains(textToFind)) {
175
                textToFind = "<b>" + textToFind + "</b>";
176
            } else {
177
                List<CatalogItem> foundItems = catalogItemRepository.getItemsByName(textToFind);
178
                if (!foundItems.isEmpty()) {
179
                    if (foundItems.stream().anyMatch(c -> c.getLatitude() != null && c.getLongitude() != null)) {
180
                        textToFind = "<span style='color:green'>" + textToFind + "</span>";
181
                    } else {
182
                        textToFind = "<span style='color:red'>" + textToFind + "</span>";
183
                    }
184
                    foundCatalogItems.add(foundItems.stream().map(this::convertEntityToDto).collect(Collectors.toList()));
185
                }
186
            }
187
            highlightedText.append(prefix).append(textToFind).append(suffix);
188
        }
189

    
190
        pathDto.setText(highlightedText.toString());
191
        pathDto.setFoundCatalogItems(foundCatalogItems);
192
        return pathDto;
193
    }
194

    
195
    @Override
196
    public List<CatalogItemDto> getCatalog(String name, String country, String type, String writtenForm) {
197
        log.info("Retrieving catalog");
198
        String finalName = name.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
199
        String finalCountry = country.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
200
        String finalType = type.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
201
        String finalWrittenForm = writtenForm.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
202

    
203
        Pattern patternName = Pattern.compile(finalName, Pattern.CASE_INSENSITIVE);
204
        Pattern patternCountry = Pattern.compile(finalCountry, Pattern.CASE_INSENSITIVE);
205
        Pattern patternType = Pattern.compile(finalType, Pattern.CASE_INSENSITIVE);
206
        Pattern patternWrittenForm = Pattern.compile(finalWrittenForm, Pattern.CASE_INSENSITIVE);
207

    
208
        List<CatalogItem> catalogItems = catalogItemRepository.findAll();
209

    
210
        Predicate<CatalogItem> predicateType = i -> finalType.equals("") || i.getTypes().stream().anyMatch(t -> patternType.matcher(t.getType()).matches());
211
        Predicate<CatalogItem> predicateCountry = i -> finalCountry.equals("") || i.getCountries().stream().anyMatch(t -> patternCountry.matcher(t.getName()).matches());
212
        Predicate<CatalogItem> predicateName = i -> finalName.equals("") || patternName.matcher(i.getName()).matches() || i.getAllNames().stream().anyMatch(t -> patternName.matcher(t.getName()).matches());
213
        Predicate<CatalogItem> predicateWrittenForm = i -> finalWrittenForm.equals("") || i.getWrittenForms().stream().anyMatch(t -> patternWrittenForm.matcher(t.getForm()).matches());
214

    
215
        catalogItems = catalogItems.stream().filter(predicateName.and(predicateCountry).and(predicateType).and(predicateWrittenForm)).collect(Collectors.toList());
216
        return catalogItems.stream().map(this::convertEntityToDto).collect(Collectors.toList());
217
    }
218

    
219
    /**
220
     * Saves catalog item to database
221
     *
222
     * @param catalogItem catalog item
223
     */
224
    private void saveCatalogEntity(CatalogItem catalogItem) {
225
        for (Type type : catalogItem.getTypes()) {
226
            if (typeService.getTypeByName(type.getType()).isEmpty()) {
227
                typeService.saveType(type);
228
            }
229
        }
230
        catalogItemRepository.save(catalogItem);
231
    }
232

    
233
    /**
234
     * Converts catalog item DTO to catalog item entity
235
     *
236
     * @param catalogItemDto catalog item DTO
237
     * @param catalogItem    catalog item entity
238
     */
239
    private void convertDtoToEntity(CatalogItemDto catalogItemDto, CatalogItem catalogItem) {
240
        AtomicInteger counter = new AtomicInteger(1);
241

    
242
        catalogItem.setName(catalogItemDto.getName());
243
        catalogItem.setCertainty(catalogItemDto.getCertainty());
244
        catalogItem.setLatitude(catalogItemDto.getLatitude());
245
        catalogItem.setLongitude(catalogItemDto.getLongitude());
246

    
247
        catalogItem.getBibliography().clear();
248
        catalogItem.getBibliography().addAll(catalogItemDto.getBibliography()
249
                .stream().map(s -> new Bibliography(s, catalogItem, counter.getAndIncrement())).collect(Collectors.toCollection(LinkedHashSet::new)));
250

    
251
        catalogItem.getTypes().clear();
252
        catalogItem.getTypes().addAll(catalogItemDto.getTypes()
253
                .stream().map(Type::new).collect(Collectors.toCollection(LinkedHashSet::new)));
254

    
255
        catalogItem.getCountries().clear();
256
        counter.set(1);
257
        catalogItem.getCountries().addAll(catalogItemDto.getCountries()
258
                .stream().map(s -> new Country(s, catalogItem, counter.getAndIncrement())).collect(Collectors.toCollection(LinkedHashSet::new)));
259

    
260
        catalogItem.getAllNames().clear();
261
        counter.set(1);
262
        Set<String> allNames = new LinkedHashSet<>();
263
        allNames.add(catalogItemDto.getName());
264
        allNames.addAll(catalogItemDto.getAllNames());
265
        catalogItem.getAllNames().addAll(allNames
266
                .stream().map(s -> new CatalogItemName(s, catalogItem, counter.getAndIncrement())).collect(Collectors.toCollection(LinkedHashSet::new)));
267

    
268
        catalogItem.getWrittenForms().clear();
269
        counter.set(1);
270
        catalogItem.getWrittenForms().addAll(catalogItemDto.getWrittenForms()
271
                .stream().map(s -> new WrittenForm(s, catalogItem, counter.getAndIncrement())).collect(Collectors.toCollection(LinkedHashSet::new)));
272

    
273
        catalogItem.setDescription(catalogItemDto.getDescription());
274
    }
275

    
276
    /**
277
     * Converts catalog item entity to catalog item DTO
278
     *
279
     * @param catalogItem catalog item entity
280
     * @return catalog item DTO
281
     */
282
    private CatalogItemDto convertEntityToDto(CatalogItem catalogItem) {
283
        CatalogItemDto catalogItemDto = new CatalogItemDto();
284
        catalogItemDto.setId(catalogItem.getId());
285
        catalogItemDto.setName(catalogItem.getName());
286
        catalogItemDto.setLatitude(catalogItem.getLatitude());
287
        catalogItemDto.setLongitude(catalogItem.getLongitude());
288
        catalogItemDto.setCertainty(catalogItem.getCertainty());
289
        catalogItemDto.setBibliography(catalogItem.getBibliography()
290
                .stream().map(Bibliography::getSource).collect(Collectors.toCollection(LinkedHashSet::new)));
291
        catalogItemDto.setTypes(catalogItem.getTypes()
292
                .stream().map(Type::getType).collect(Collectors.toCollection(LinkedHashSet::new)));
293
        catalogItemDto.setCountries(catalogItem.getCountries()
294
                .stream().map(Country::getName).collect(Collectors.toCollection(LinkedHashSet::new)));
295
        catalogItemDto.setAllNames(catalogItem.getAllNames()
296
                .stream().map(CatalogItemName::getName).collect(Collectors.toCollection(LinkedHashSet::new)));
297
        catalogItemDto.setWrittenForms(catalogItem.getWrittenForms()
298
                .stream().map(WrittenForm::getForm).collect(Collectors.toCollection(LinkedHashSet::new)));
299
        catalogItemDto.setDescription(catalogItem.getDescription());
300
        return catalogItemDto;
301
    }
302

    
303
}
(5-5/6)