Projekt

Obecné

Profil

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

    
3
import cz.zcu.kiv.backendapi.alternativename.AlternativeName;
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.springframework.http.HttpStatus;
14
import org.springframework.stereotype.Service;
15
import org.springframework.transaction.annotation.Transactional;
16

    
17
import java.util.ArrayList;
18
import java.util.List;
19
import java.util.Set;
20
import java.util.UUID;
21
import java.util.function.Predicate;
22
import java.util.regex.Matcher;
23
import java.util.regex.Pattern;
24
import java.util.stream.Collectors;
25

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

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

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

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

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

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

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

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

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

    
79

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

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

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

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

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

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

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

    
132
        return convertEntityToDto(catalogItem);
133
    }
134

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

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

    
143
        String[] tokens = text.split("\\s+");
144
        for (String token : tokens) {
145
            Matcher matcherStart = START_PUNCTUATION_PATTERN.matcher(token);
146
            Matcher matcherEnd = END_PUNCTUATION_PATTERN.matcher(token);
147
            String prefix = "";
148
            String suffix = "";
149
            String textToFind;
150
            int startTextIndex = 0;
151
            int endTextIndex = token.length();
152

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

    
164
            if (endTextIndex < startTextIndex) {
165
                highlightedText.append(prefix).append(" ");
166
                continue;
167
            }
168

    
169
            textToFind = token.substring(startTextIndex, endTextIndex);
170

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

    
188
        pathDto.setText(highlightedText.toString());
189
        pathDto.setFoundCatalogItems(foundCatalogItems);
190
        return pathDto;
191
    }
192

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

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

    
206
        List<CatalogItem> catalogItems = catalogItemRepository.findAll();
207

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

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

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

    
231
    /**
232
     * Converts catalog item DTO to catalog item entity
233
     *
234
     * @param catalogItemDto catalog item DTO
235
     * @param catalogItem    catalog item entity
236
     */
237
    private void convertDtoToEntity(CatalogItemDto catalogItemDto, CatalogItem catalogItem) {
238
        catalogItem.setName(catalogItemDto.getName());
239
        catalogItem.setCertainty(catalogItemDto.getCertainty());
240
        catalogItem.setLatitude(catalogItemDto.getLatitude());
241
        catalogItem.setLongitude(catalogItemDto.getLongitude());
242

    
243
        catalogItem.getBibliography().clear();
244
        catalogItem.getBibliography().addAll(catalogItemDto.getBibliography()
245
                .stream().map(s -> new Bibliography(s, catalogItem)).collect(Collectors.toSet()));
246

    
247
        catalogItem.getTypes().clear();
248
        catalogItem.getTypes().addAll(catalogItemDto.getTypes()
249
                .stream().map(Type::new).collect(Collectors.toSet()));
250

    
251
        catalogItem.getCountries().clear();
252
        catalogItem.getCountries().addAll(catalogItemDto.getCountries()
253
                .stream().map(s -> new Country(s, catalogItem)).collect(Collectors.toSet()));
254

    
255
        catalogItemDto.getAlternativeNames().add(catalogItemDto.getName());
256
        catalogItem.getAlternativeNames().clear();
257
        catalogItem.getAlternativeNames().addAll(catalogItemDto.getAlternativeNames()
258
                .stream().map(s -> new AlternativeName(s, catalogItem)).collect(Collectors.toSet()));
259

    
260
        catalogItem.getWrittenForms().clear();
261
        catalogItem.getWrittenForms().addAll(catalogItemDto.getWrittenForms()
262
                .stream().map(s -> new WrittenForm(s, catalogItem)).collect(Collectors.toSet()));
263

    
264
        catalogItem.setDescription(catalogItemDto.getDescription());
265
    }
266

    
267
    /**
268
     * Converts catalog item entity to catalog item DTO
269
     *
270
     * @param catalogItem catalog item entity
271
     * @return catalog item DTO
272
     */
273
    private CatalogItemDto convertEntityToDto(CatalogItem catalogItem) {
274
        CatalogItemDto catalogItemDto = new CatalogItemDto();
275
        catalogItemDto.setId(catalogItem.getId());
276
        catalogItemDto.setName(catalogItem.getName());
277
        catalogItemDto.setLatitude(catalogItem.getLatitude());
278
        catalogItemDto.setLongitude(catalogItem.getLongitude());
279
        catalogItemDto.setCertainty(catalogItem.getCertainty());
280
        catalogItemDto.setBibliography(catalogItem.getBibliography()
281
                .stream().map(Bibliography::getSource).collect(Collectors.toSet()));
282
        catalogItemDto.setTypes(catalogItem.getTypes()
283
                .stream().map(Type::getType).collect(Collectors.toSet()));
284
        catalogItemDto.setCountries(catalogItem.getCountries()
285
                .stream().map(Country::getName).collect(Collectors.toSet()));
286
        catalogItemDto.setAlternativeNames(catalogItem.getAlternativeNames()
287
                .stream().map(AlternativeName::getName).collect(Collectors.toSet()));
288
        catalogItemDto.setWrittenForms(catalogItem.getWrittenForms()
289
                .stream().map(WrittenForm::getForm).collect(Collectors.toSet()));
290
        catalogItemDto.setDescription(catalogItem.getDescription());
291
        return catalogItemDto;
292
    }
293

    
294
}
(5-5/6)