Projekt

Obecné

Profil

« Předchozí | Další » 

Revize b539ef29

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

Added path
- searching and highlighting text
- returning list of found catalog items

re #9490

Zobrazit rozdíly:

backend/docker-compose.yml
28 28
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/test # overwrites application.properties datasource url to connect to the database
29 29

  
30 30
  frontend:
31
    # Since our Dockerfile for web-server is located in react-app foler, our build context is ./react-app
31
#     Since our Dockerfile for web-server is located in react-app folder, our build context is ./react-app
32 32
    build: ../frontend
33 33
    container_name: frontend
34 34
    image: schwobik/frontend-app:1.2
backend/pom.xml
23 23
        </dependency>
24 24

  
25 25
        <dependency>
26
            <groupId>org.projectlombok</groupId>
27
            <artifactId>lombok</artifactId>
26
            <groupId>org.springframework.boot</groupId>
27
            <artifactId>spring-boot-configuration-processor</artifactId>
28 28
            <optional>true</optional>
29 29
        </dependency>
30

  
30 31
        <dependency>
31 32
            <groupId>org.springframework.boot</groupId>
32 33
            <artifactId>spring-boot-starter-test</artifactId>
33 34
            <scope>test</scope>
34 35
        </dependency>
35 36

  
36
        <dependency>
37
            <groupId>com.h2database</groupId>
38
            <artifactId>h2</artifactId>
39
            <scope>test</scope>
40
        </dependency>
41

  
42
        <dependency>
43
            <groupId>org.postgresql</groupId>
44
            <artifactId>postgresql</artifactId>
45
            <scope>runtime</scope>
46
        </dependency>
47

  
48 37
        <dependency>
49 38
            <groupId>org.springframework.boot</groupId>
50 39
            <artifactId>spring-boot-starter-data-jpa</artifactId>
......
64 53
            <groupId>org.springframework.security</groupId>
65 54
            <artifactId>spring-security-test</artifactId>
66 55
            <scope>test</scope>
56
            <version>5.6.2</version>
57
        </dependency>
58

  
59
        <dependency>
60
            <groupId>org.projectlombok</groupId>
61
            <artifactId>lombok</artifactId>
62
            <optional>true</optional>
63
            <version>1.18.22</version>
64
        </dependency>
65

  
66
        <dependency>
67
            <groupId>com.h2database</groupId>
68
            <artifactId>h2</artifactId>
69
            <scope>test</scope>
70
            <version>2.1.210</version>
71
        </dependency>
72

  
73
        <dependency>
74
            <groupId>org.postgresql</groupId>
75
            <artifactId>postgresql</artifactId>
76
            <scope>runtime</scope>
77
            <version>42.3.3</version>
67 78
        </dependency>
68 79

  
69 80
        <dependency>
......
75 86
        <dependency>
76 87
            <groupId>com.auth0</groupId>
77 88
            <artifactId>java-jwt</artifactId>
78
            <version>3.19.0</version>
89
            <version>3.19.1</version>
79 90
        </dependency>
80 91

  
81 92
        <dependency>
......
84 95
            <version>31.1-jre</version>
85 96
        </dependency>
86 97

  
87
        <dependency>
88
            <groupId>org.springframework.boot</groupId>
89
            <artifactId>spring-boot-configuration-processor</artifactId>
90
            <version>2.6.5</version>
91
            <optional>true</optional>
92
        </dependency>
93

  
94 98
        <dependency>
95 99
            <groupId>org.springdoc</groupId>
96 100
            <artifactId>springdoc-openapi-ui</artifactId>
97
            <version>1.6.6</version>
101
            <version>1.6.7</version>
98 102
        </dependency>
99 103
    </dependencies>
100 104

  
backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameServiceImpl.java
1
package cz.zcu.kiv.backendapi.alternativename;
2

  
3
import lombok.RequiredArgsConstructor;
4
import org.springframework.stereotype.Service;
5
import org.springframework.transaction.annotation.Transactional;
6

  
7
/**
8
 * Alternative name service implementation
9
 */
10
@Service
11
@Transactional
12
@RequiredArgsConstructor
13
public class AlternativeNameServiceImpl implements IAlternativeNameService {
14

  
15
    /**
16
     * Alternative name repository
17
     */
18
    private final AlternativeNameRepository alternativeNameRepository;
19
}
backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/IAlternativeNameService.java
1
package cz.zcu.kiv.backendapi.alternativename;
2

  
3
/**
4
 * Alternative name service interface
5
 */
6
public interface IAlternativeNameService {
7
}
backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyServiceImpl.java
1
package cz.zcu.kiv.backendapi.bibliography;
2

  
3
import lombok.RequiredArgsConstructor;
4
import org.springframework.stereotype.Service;
5
import org.springframework.transaction.annotation.Transactional;
6

  
7
/**
8
 * Bibliography service implementation
9
 */
10
@Service
11
@Transactional
12
@RequiredArgsConstructor
13
public class BibliographyServiceImpl implements IBibliographyService {
14
    /**
15
     * Bibliography repository
16
     */
17
    private final BibliographyRepository bibliographyRepository;
18
}
backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/IBibliographyService.java
1
package cz.zcu.kiv.backendapi.bibliography;
2

  
3
/**
4
 * Bibliography service interface
5
 */
6
public interface IBibliographyService {
7
}
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java
76 76
     * @param id ID
77 77
     * @return catalog item with given ID
78 78
     */
79
    @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json")
79
    @GetMapping(value = "/{id}")
80 80
    @Operation(summary = "returns catalog item with given ID")
81 81
    public CatalogItemDto getCatalogItem(@PathVariable UUID id) {
82 82
        return catalogService.getCatalogItem(id);
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemDto.java
28 28
    private String name;
29 29

  
30 30
    /**
31
     * Certainty
31
     * Alternative names
32 32
     */
33
    private int certainty;
33
    private Set<String> alternativeNames = Collections.emptySet();
34 34

  
35 35
    /**
36
     * Longitude
36
     * Written forms
37 37
     */
38
    private double longitude;
38
    private Set<String> writtenForms = Collections.emptySet();
39 39

  
40 40
    /**
41
     * Latitude
41
     * Types
42 42
     */
43
    private double latitude;
43
    private Set<String> types = Collections.emptySet();
44 44

  
45 45
    /**
46
     * Bibliography
46
     * Countries
47 47
     */
48
    private Set<String> bibliography = Collections.emptySet();
48
    private Set<String> countries = Collections.emptySet();
49 49

  
50 50
    /**
51
     * Countries
51
     * Bibliography
52 52
     */
53
    private Set<String> countries = Collections.emptySet();
53
    private Set<String> bibliography = Collections.emptySet();
54 54

  
55 55
    /**
56
     * Written forms
56
     * Longitude
57 57
     */
58
    private Set<String> writtenForms = Collections.emptySet();
58
    private double longitude;
59 59

  
60 60
    /**
61
     * Alternative names
61
     * Latitude
62 62
     */
63
    private Set<String> alternativeNames = Collections.emptySet();
63
    private double latitude;
64 64

  
65 65
    /**
66
     * Types
66
     * Certainty
67 67
     */
68
    private Set<String> types = Collections.emptySet();
68
    private int certainty;
69 69

  
70 70
}
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepository.java
4 4
import org.springframework.data.jpa.repository.Query;
5 5
import org.springframework.stereotype.Repository;
6 6

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

  
......
29 30
            "AND (?2 = '' OR UPPER(c.name) LIKE UPPER(?2)) " +
30 31
            "AND (?3 = '' OR UPPER(t.type) LIKE UPPER(?3))")
31 32
    Set<CatalogItem> filterCatalog(String name, String country, String type);
33

  
34
    /**
35
     * Selects catalog items with given name (alternative name)
36
     *
37
     * @param name name
38
     * @return list of catalog items with given name
39
     */
40
    @Query("SELECT DISTINCT a.catalogItem FROM AlternativeName a WHERE ?1 = a.name")
41
    List<CatalogItem> getItemsByName(String name);
32 42
}
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImpl.java
4 4
import cz.zcu.kiv.backendapi.bibliography.Bibliography;
5 5
import cz.zcu.kiv.backendapi.country.Country;
6 6
import cz.zcu.kiv.backendapi.exception.ApiRequestException;
7
import cz.zcu.kiv.backendapi.path.PathDto;
7 8
import cz.zcu.kiv.backendapi.type.ITypeService;
8 9
import cz.zcu.kiv.backendapi.type.Type;
9 10
import cz.zcu.kiv.backendapi.writtenform.WrittenForm;
......
13 14
import org.springframework.stereotype.Service;
14 15
import org.springframework.transaction.annotation.Transactional;
15 16

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

  
21 25
/**
......
41 45
     */
42 46
    private static final String WILDCARD_CHARACTERS_REGEX = "\\*";
43 47

  
48
    /**
49
     * Regex for finding punctuation at the start of word
50
     */
51
    private static final String START_PUNCTUATION_REGEX = "^[\\p{Punct}\\p{IsPunctuation}]+";
52

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

  
58
    /**
59
     * Pattern for finding punctuation at the start of word
60
     */
61
    private static final Pattern START_PUNCTUATION_PATTERN = Pattern.compile(START_PUNCTUATION_REGEX);
62

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

  
44 68
    /**
45 69
     * Regex for any number of arbitrary characters in string used in SQL language
46 70
     */
......
51 75
     */
52 76
    private static final String CATALOG_ITEM_NOT_FOUND = "Catalog item not found";
53 77

  
78
    /**
79
     * Threshold for comparing doubles
80
     */
81
    private static final double DOUBLE_THRESHOLD = 0.001;
82

  
54 83
    /**
55 84
     * Catalog repository
56 85
     */
......
111 140

  
112 141
    @Override
113 142
    public CatalogItemDto getCatalogItem(UUID id) {
114
        var catalogItem = catalogItemRepository.findById(id).orElseThrow(() -> {
143
        CatalogItem catalogItem = catalogItemRepository.findById(id).orElseThrow(() -> {
115 144
            log.error(CATALOG_ITEM_NOT_FOUND);
116 145
            throw new ApiRequestException(CATALOG_ITEM_NOT_FOUND, HttpStatus.NOT_FOUND);
117 146
        });
......
119 148
        return convertEntityToDto(catalogItem);
120 149
    }
121 150

  
151
    @Override
152
    public PathDto getPath(String text) {
153
        PathDto pathDto = new PathDto();
154
        StringBuilder highlightedText = new StringBuilder();
155
        List<List<CatalogItemDto>> foundCatalogItems = new ArrayList<>();
156

  
157
        Set<String> types = typeService.getAllTypesAsString();
158

  
159
        String[] tokens = text.split("\\s+");
160
        for (String token : tokens) {
161
            Matcher matcherStart = START_PUNCTUATION_PATTERN.matcher(token);
162
            Matcher matcherEnd = END_PUNCTUATION_PATTERN.matcher(token);
163
            String prefix = "";
164
            String suffix = "";
165
            String textToFind;
166
            int startTextIndex = 0;
167
            int endTextIndex = token.length();
168

  
169
            if (matcherStart.find()) {
170
                int start = matcherStart.start();
171
                startTextIndex = matcherStart.end();
172
                prefix = token.substring(start, startTextIndex);
173
            }
174
            if (matcherEnd.find()) {
175
                endTextIndex = matcherEnd.start();
176
                int end = matcherEnd.end();
177
                suffix = token.substring(endTextIndex, end);
178
            }
179

  
180
            textToFind = token.substring(startTextIndex, endTextIndex);
181

  
182
            if (types.contains(textToFind)) {
183
                textToFind = "<b>" + textToFind + "</b>";
184
            } else {
185
                List<CatalogItem> foundItems = catalogItemRepository.getItemsByName(textToFind);
186
                if (!foundItems.isEmpty()) {
187
                    if (foundItems.stream().anyMatch(c -> Math.abs(c.getLatitude()) > DOUBLE_THRESHOLD && Math.abs(c.getLongitude()) > DOUBLE_THRESHOLD)) {
188
                        textToFind = "<span style='color:green'>" + textToFind + "</span>";
189
                    } else {
190
                        textToFind = "<span style='color:red'>" + textToFind + "</span>";
191
                    }
192
                    foundCatalogItems.add(foundItems.stream().map(this::convertEntityToDto).collect(Collectors.toList()));
193
                }
194
            }
195
            highlightedText.append(prefix).append(textToFind).append(suffix).append(" ");
196
        }
197
        highlightedText.setLength(highlightedText.length() - 1);
198

  
199
        pathDto.setText(highlightedText.toString());
200
        pathDto.setFoundCatalogItems(foundCatalogItems);
201
        return pathDto;
202
    }
203

  
122 204
    /**
123 205
     * Saves catalog entity to database
124 206
     *
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogItemService.java
1 1
package cz.zcu.kiv.backendapi.catalog;
2 2

  
3
import cz.zcu.kiv.backendapi.path.PathDto;
4

  
3 5
import java.util.List;
4 6
import java.util.UUID;
5 7

  
......
54 56
     */
55 57
    CatalogItemDto getCatalogItem(UUID id);
56 58

  
59
    /**
60
     * Returns highlighted searched text and searched items
61
     *
62
     * @param text text
63
     * @return highlighted searched text and searched items
64
     */
65
    PathDto getPath(String text);
66

  
57 67
}
backend/src/main/java/cz/zcu/kiv/backendapi/config/DataInitiator.java
21 21

  
22 22
import java.io.File;
23 23
import java.io.IOException;
24
import java.io.InputStream;
24 25
import java.nio.charset.Charset;
25 26
import java.nio.charset.StandardCharsets;
26 27
import java.util.ArrayList;
......
65 66

  
66 67
    private List<CatalogItem> loadCatalog() {
67 68
        List<CatalogItem> catalogEntities = new ArrayList<>();
68
        var csvData = getClass().getClassLoader().getResourceAsStream("AssyrianProject-AllNoDupl-22-03-28.csv");
69
        InputStream csvData = getClass().getClassLoader().getResourceAsStream("AssyrianProject-AllNoDupl-22-03-28.csv");
69 70
//        File csvData = new File("AssyrianProject-AllNoDupl-22-03-28.csv");
70 71
        CSVParser parser;
71 72
        try {
backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryServiceImpl.java
1
package cz.zcu.kiv.backendapi.country;
2

  
3
import lombok.RequiredArgsConstructor;
4
import org.springframework.stereotype.Service;
5
import org.springframework.transaction.annotation.Transactional;
6

  
7
/**
8
 * Country service implementation
9
 */
10
@Service
11
@Transactional
12
@RequiredArgsConstructor
13
public class CountryServiceImpl implements ICountryService {
14

  
15
    /**
16
     * Country repository
17
     */
18
    private final CountryRepository countryRepository;
19
}
backend/src/main/java/cz/zcu/kiv/backendapi/country/ICountryService.java
1
package cz.zcu.kiv.backendapi.country;
2

  
3
/**
4
 * Country service interface
5
 */
6
public interface ICountryService {
7
}
backend/src/main/java/cz/zcu/kiv/backendapi/path/PathController.java
1
package cz.zcu.kiv.backendapi.path;
2

  
3
import cz.zcu.kiv.backendapi.catalog.ICatalogItemService;
4
import lombok.RequiredArgsConstructor;
5
import org.springframework.web.bind.annotation.GetMapping;
6
import org.springframework.web.bind.annotation.RequestBody;
7
import org.springframework.web.bind.annotation.RequestMapping;
8
import org.springframework.web.bind.annotation.RestController;
9

  
10
/**
11
 * Controller for paths
12
 */
13
@RestController
14
@RequiredArgsConstructor
15
@RequestMapping("/path")
16
public class PathController {
17

  
18
    /**
19
     * Catalog item service
20
     */
21
    private final ICatalogItemService catalogItemService;
22

  
23
    /**
24
     * Returns path with highlighted text and found catalog items
25
     *
26
     * @param pathDto catalog DTO with text to be searched
27
     * @return path DTO with highlighted text and found catalog items
28
     */
29
    @GetMapping("")
30
    public PathDto getPath(@RequestBody PathDto pathDto) {
31
        return catalogItemService.getPath(pathDto.getText());
32
    }
33
}
backend/src/main/java/cz/zcu/kiv/backendapi/path/PathDto.java
1
package cz.zcu.kiv.backendapi.path;
2

  
3
import com.fasterxml.jackson.annotation.JsonProperty;
4
import cz.zcu.kiv.backendapi.catalog.CatalogItemDto;
5
import lombok.AllArgsConstructor;
6
import lombok.Data;
7
import lombok.NoArgsConstructor;
8

  
9
import java.util.List;
10

  
11
/**
12
 * Class representing DTO for path
13
 */
14
@Data
15
@AllArgsConstructor
16
@NoArgsConstructor
17
public class PathDto {
18
    /**
19
     * Text to be searched / highlighted text
20
     */
21
    private String text;
22

  
23
    /**
24
     * List of lists of found catalog items
25
     */
26
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
27
    private List<List<CatalogItemDto>> foundCatalogItems;
28
}
backend/src/main/java/cz/zcu/kiv/backendapi/type/ITypeService.java
1 1
package cz.zcu.kiv.backendapi.type;
2 2

  
3 3
import java.util.Optional;
4
import java.util.Set;
4 5

  
5 6
/**
6 7
 * Type service interface
......
21 22
     * @return type by name (optional)
22 23
     */
23 24
    Optional<Type> getTypeByName(String type);
25

  
26
    /**
27
     * Returns set of all types as string
28
     *
29
     * @return set of all types as string
30
     */
31
    Set<String> getAllTypesAsString();
24 32
}
backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeServiceImpl.java
5 5
import org.springframework.transaction.annotation.Transactional;
6 6

  
7 7
import java.util.Optional;
8
import java.util.Set;
9
import java.util.stream.Collectors;
8 10

  
9 11
/**
10 12
 * Type service implementation
......
28 30
        return typeRepository.findById(type);
29 31
    }
30 32

  
33
    @Override
34
    public Set<String> getAllTypesAsString() {
35
        return typeRepository.findAll().stream().map(Type::getType).collect(Collectors.toSet());
36
    }
37

  
31 38

  
32 39
}
backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/IWrittenFormService.java
1
package cz.zcu.kiv.backendapi.writtenform;
2

  
3
/**
4
 * Written form service interface
5
 */
6
public interface IWrittenFormService {
7
}
backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormServiceImpl.java
1
package cz.zcu.kiv.backendapi.writtenform;
2

  
3
import lombok.RequiredArgsConstructor;
4
import org.springframework.stereotype.Service;
5
import org.springframework.transaction.annotation.Transactional;
6

  
7
/**
8
 * Written form service implementation
9
 */
10
@Service
11
@Transactional
12
@RequiredArgsConstructor
13
public class WrittenFormServiceImpl implements IWrittenFormService {
14

  
15
    /**
16
     * Written form repository
17
     */
18
    private final WrittenFormRepository writtenFormRepository;
19
}

Také k dispozici: Unified diff