Projekt

Obecné

Profil

Stáhnout (12.1 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
            textToFind = token.substring(startTextIndex, endTextIndex);
165

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

    
183
        pathDto.setText(highlightedText.toString());
184
        pathDto.setFoundCatalogItems(foundCatalogItems);
185
        return pathDto;
186
    }
187

    
188
    @Override
189
    public List<CatalogItemDto> getCatalog(String name, String country, String type, String writtenForm) {
190
        log.info("Retrieving catalog");
191
        String finalName = name.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
192
        String finalCountry = country.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
193
        String finalType = type.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
194
        String finalWrittenForm = writtenForm.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
195

    
196
        Pattern patternName = Pattern.compile(finalName, Pattern.CASE_INSENSITIVE);
197
        Pattern patternCountry = Pattern.compile(finalCountry, Pattern.CASE_INSENSITIVE);
198
        Pattern patternType = Pattern.compile(finalType, Pattern.CASE_INSENSITIVE);
199
        Pattern patternWrittenForm = Pattern.compile(finalWrittenForm, Pattern.CASE_INSENSITIVE);
200

    
201
        List<CatalogItem> catalogItems = catalogItemRepository.findAll();
202

    
203
        Predicate<CatalogItem> predicateType = i -> finalType.equals("") || i.getTypes().stream().anyMatch(t -> patternType.matcher(t.getType()).matches());
204
        Predicate<CatalogItem> predicateCountry = i -> finalCountry.equals("") || i.getCountries().stream().anyMatch(t -> patternCountry.matcher(t.getName()).matches());
205
        Predicate<CatalogItem> predicateName = i -> finalName.equals("") || patternName.matcher(i.getName()).matches() || i.getAlternativeNames().stream().anyMatch(t -> patternName.matcher(t.getName()).matches());
206
        Predicate<CatalogItem> predicateWrittenForm = i -> finalWrittenForm.equals("") || i.getWrittenForms().stream().anyMatch(t -> patternWrittenForm.matcher(t.getForm()).matches());
207

    
208
        catalogItems = catalogItems.stream().filter(predicateName.and(predicateCountry).and(predicateType).and(predicateWrittenForm)).collect(Collectors.toList());
209
        return catalogItems.stream().map(this::convertEntityToDto).collect(Collectors.toList());
210
    }
211

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

    
226
    /**
227
     * Converts catalog DTO to catalog entity
228
     *
229
     * @param catalogItemDto catalog DTO
230
     * @param catalogItem    catalog entity
231
     */
232
    private void convertDtoToEntity(CatalogItemDto catalogItemDto, CatalogItem catalogItem) {
233
        catalogItem.setName(catalogItemDto.getName());
234
        catalogItem.setCertainty(catalogItemDto.getCertainty());
235
        catalogItem.setLatitude(catalogItemDto.getLatitude());
236
        catalogItem.setLongitude(catalogItemDto.getLongitude());
237

    
238
        catalogItem.getBibliography().clear();
239
        catalogItem.getBibliography().addAll(catalogItemDto.getBibliography()
240
                .stream().map(s -> new Bibliography(s, catalogItem)).collect(Collectors.toSet()));
241

    
242
        catalogItem.getTypes().clear();
243
        catalogItem.getTypes().addAll(catalogItemDto.getTypes()
244
                .stream().map(Type::new).collect(Collectors.toSet()));
245

    
246
        catalogItem.getCountries().clear();
247
        catalogItem.getCountries().addAll(catalogItemDto.getCountries()
248
                .stream().map(s -> new Country(s, catalogItem)).collect(Collectors.toSet()));
249

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

    
254
        catalogItem.getWrittenForms().clear();
255
        catalogItem.getWrittenForms().addAll(catalogItemDto.getWrittenForms()
256
                .stream().map(s -> new WrittenForm(s, catalogItem)).collect(Collectors.toSet()));
257

    
258
        catalogItem.setDescription(catalogItemDto.getDescription());
259
    }
260

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

    
288
}
(5-5/6)