commit d6451c0a3f9d4824d32eeddfb04d40f7b90bc46c
Author: Jakub Smid <jaksmid@seznam.cz>
Date:   Fri Apr 22 17:22:20 2022 +0200

    Added filter for written forms and some tests
    
    re #9492

diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeName.java b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeName.java
index 9ccd5eb..051f7f9 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeName.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeName.java
@@ -1,23 +1,24 @@
 package cz.zcu.kiv.backendapi.alternativename;
 
 import cz.zcu.kiv.backendapi.catalog.CatalogItem;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
 
 import javax.persistence.*;
-import java.io.Serializable;
 
 /**
  * Alternative name entity representing alternative name of catalog item
  */
-@Data
-@EqualsAndHashCode(exclude = "catalogItem")
-@ToString(exclude = "catalogItem")
+@Getter
+@Setter
 @NoArgsConstructor
 @AllArgsConstructor
 @Entity
 @Table(name = "alternative_names")
-@IdClass(AlternativeName.class)
-public class AlternativeName implements Serializable {
+@IdClass(AlternativeNamePK.class)
+public class AlternativeName {
     /**
      * Name, serves as ID
      */
@@ -27,8 +28,8 @@ public class AlternativeName implements Serializable {
     /**
      * Catalog entity
      */
-    @ManyToOne
-    @JoinColumn(name = "catalog_item_id")
+    @ManyToOne(fetch = FetchType.LAZY)
     @Id
+    @JoinColumn(name = "catalog_item_id")
     private CatalogItem catalogItem;
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNamePK.java b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNamePK.java
new file mode 100644
index 0000000..0b8b491
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNamePK.java
@@ -0,0 +1,26 @@
+package cz.zcu.kiv.backendapi.alternativename;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+/**
+ * Class representing alternative name primary key
+ */
+@EqualsAndHashCode
+@AllArgsConstructor
+@NoArgsConstructor
+public class AlternativeNamePK implements Serializable {
+    /**
+     * Name
+     */
+    private String name;
+
+    /**
+     * ID of catalog item
+     */
+    private UUID catalogItem;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/Bibliography.java b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/Bibliography.java
index 7b34566..0758a7a 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/Bibliography.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/Bibliography.java
@@ -1,30 +1,32 @@
 package cz.zcu.kiv.backendapi.bibliography;
 
 import cz.zcu.kiv.backendapi.catalog.CatalogItem;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
 
 import javax.persistence.*;
-import java.io.Serializable;
 
 /**
  * Bibliography entity representing bibliography
  */
-@Data
-@EqualsAndHashCode(exclude = "catalogItem")
-@ToString(exclude = "catalogItem")
+@Getter
+@Setter
 @NoArgsConstructor
 @AllArgsConstructor
 @Entity
 @Table(name = "bibliography")
-@IdClass(Bibliography.class)
-public class Bibliography implements Serializable {
+@IdClass(BibliographyPK.class)
+public class Bibliography {
     /**
      * Source, serves as ID
      */
     @Id
     private String source;
 
-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY)
+    @Id
     @JoinColumn(name = "catalog_item_id")
     private CatalogItem catalogItem;
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyPK.java b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyPK.java
new file mode 100644
index 0000000..df3f471
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyPK.java
@@ -0,0 +1,26 @@
+package cz.zcu.kiv.backendapi.bibliography;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+/**
+ * Class representing bibliography primary key
+ */
+@EqualsAndHashCode
+@AllArgsConstructor
+@NoArgsConstructor
+public class BibliographyPK implements Serializable {
+    /**
+     * Source
+     */
+    private String source;
+
+    /**
+     * ID of catalog item
+     */
+    private UUID catalogItem;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java
index 165f69b..23ebb96 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java
@@ -43,8 +43,8 @@ public class CatalogController {
      */
     @GetMapping("")
     @Operation(summary = "returns catalog items based on filter")
-    public ResponseEntity<List<CatalogItemDto>> getCatalog(@RequestParam(defaultValue = "") String name, @RequestParam(defaultValue = "") String country, @RequestParam(defaultValue = "") String type) {
-        return new ResponseEntity<>(catalogService.getCatalog(name, country, type), HttpStatus.OK);
+    public ResponseEntity<List<CatalogItemDto>> getCatalog(@RequestParam(defaultValue = "") String name, @RequestParam(defaultValue = "") String country, @RequestParam(defaultValue = "") String type, @RequestParam(defaultValue = "") String writtenForm) {
+        return new ResponseEntity<>(catalogService.getCatalog(name, country, type, writtenForm), HttpStatus.OK);
     }
 
     /**
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItem.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItem.java
index 16bfd91..8e1ea01 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItem.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItem.java
@@ -5,8 +5,10 @@ import cz.zcu.kiv.backendapi.bibliography.Bibliography;
 import cz.zcu.kiv.backendapi.country.Country;
 import cz.zcu.kiv.backendapi.type.Type;
 import cz.zcu.kiv.backendapi.writtenform.WrittenForm;
-import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
 import lombok.NoArgsConstructor;
+import lombok.Setter;
 import org.hibernate.annotations.Fetch;
 import org.hibernate.annotations.FetchMode;
 import org.hibernate.annotations.LazyCollection;
@@ -21,7 +23,9 @@ import java.util.stream.Collectors;
 /**
  * Catalog entity representing catalog item
  */
-@Data
+@Getter
+@Setter
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
 @NoArgsConstructor
 @Entity
 @Table(name = "catalog_item")
@@ -33,8 +37,9 @@ public class CatalogItem {
      * Catalog item id
      */
     @Id
-    @GeneratedValue
-    private UUID id;
+//    @GeneratedValue
+    @EqualsAndHashCode.Include
+    private UUID id = UUID.randomUUID();
 
     /**
      * Name of geographic item
@@ -68,7 +73,7 @@ public class CatalogItem {
     @OneToMany(mappedBy = "catalogItem", cascade = CascadeType.ALL)
     @LazyCollection(LazyCollectionOption.FALSE)
     @Fetch(FetchMode.SUBSELECT)
-    private Set<Bibliography> bibliography = Collections.emptySet();
+    private Set<Bibliography> bibliography = new HashSet<>();
 
     /**
      * Countries
@@ -76,7 +81,7 @@ public class CatalogItem {
     @OneToMany(mappedBy = "catalogItem", cascade = CascadeType.ALL)
     @LazyCollection(LazyCollectionOption.FALSE)
     @Fetch(FetchMode.SUBSELECT)
-    private Set<Country> countries = Collections.emptySet();
+    private Set<Country> countries = new HashSet<>();
 
     /**
      * Written forms
@@ -84,7 +89,7 @@ public class CatalogItem {
     @OneToMany(mappedBy = "catalogItem", cascade = CascadeType.ALL)
     @LazyCollection(LazyCollectionOption.FALSE)
     @Fetch(FetchMode.SUBSELECT)
-    private Set<WrittenForm> writtenForms = Collections.emptySet();
+    private Set<WrittenForm> writtenForms = new HashSet<>();
 
     /**
      * Alternative names
@@ -92,7 +97,7 @@ public class CatalogItem {
     @OneToMany(mappedBy = "catalogItem", cascade = CascadeType.ALL)
     @LazyCollection(LazyCollectionOption.FALSE)
     @Fetch(FetchMode.SUBSELECT)
-    private Set<AlternativeName> alternativeNames = Collections.emptySet();
+    private Set<AlternativeName> alternativeNames = new HashSet<>();
 
     /**
      * Set of user roles - many-to-many relationship
@@ -108,12 +113,12 @@ public class CatalogItem {
                     @JoinColumn(name = "type", referencedColumnName = "type")
             }
     )
-    private Set<Type> types = Collections.emptySet();
+    private Set<Type> types = new HashSet<>();
 
     public CatalogItem(final List<String> csvFields) {
 
         this.name = csvFields.get(1);
-        List<String> stringList = processListField(csvFields.get(2));
+        Set<String> stringList = processListField(csvFields.get(2));
         this.alternativeNames = stringList.stream().map(s -> new AlternativeName(s, this)).collect(Collectors.toSet());
 
         this.certainty = processIntField(csvFields.get(3));
@@ -151,10 +156,10 @@ public class CatalogItem {
         }
     }
 
-    private List<String> processListField(String field) {
+    private Set<String> processListField(String field) {
         if (field.isEmpty() || field.equals(EMPTY_ENTRY)) {
-            return new ArrayList<>();
+            return new HashSet<>();
         }
-        return Arrays.stream(field.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toList());
+        return Arrays.stream(field.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toSet());
     }
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepository.java
index 3e019c7..7dc53bc 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepository.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepository.java
@@ -5,7 +5,6 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 
 import java.util.List;
-import java.util.Set;
 import java.util.UUID;
 
 /**
@@ -14,23 +13,6 @@ import java.util.UUID;
 @Repository
 public interface CatalogItemRepository extends JpaRepository<CatalogItem, UUID> {
 
-    /**
-     * Returns all catalog items containing specific values
-     *
-     * @param name    name - optional
-     * @param country country - optional
-     * @param type    type - optional
-     * @return set of catalog items satisfying filter conditions
-     */
-    @Query("SELECT DISTINCT e FROM CatalogItem e " +
-            "LEFT JOIN FETCH AlternativeName a ON e = a.catalogItem " +
-            "LEFT JOIN FETCH Country c ON e = c.catalogItem " +
-            "LEFT JOIN FETCH e.types t " +
-            "WHERE (?1 = '' OR UPPER(e.name) LIKE UPPER(?1) OR UPPER(a.name) LIKE UPPER(?1)) " +
-            "AND (?2 = '' OR UPPER(c.name) LIKE UPPER(?2)) " +
-            "AND (?3 = '' OR UPPER(t.type) LIKE UPPER(?3))")
-    Set<CatalogItem> filterCatalog(String name, String country, String type);
-
     /**
      * Selects catalog items with given name (alternative name)
      *
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImpl.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImpl.java
index 03d48da..f17a8c2 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImpl.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImpl.java
@@ -14,10 +14,8 @@ import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
+import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -36,15 +34,20 @@ public class CatalogItemServiceImpl implements ICatalogItemService {
     private static final String WILDCARD_CHARACTER_REGEX = "\\?";
 
     /**
-     * Regex for one arbitrary character in string used in SQL language
+     * Regex for one arbitrary character in string used in Java
      */
-    private static final String WILDCARD_CHARACTER_REGEX_SQL = "_";
+    private static final String WILDCARD_CHARACTER_REGEX_JAVA = ".";
 
     /**
      * Regex for any number of arbitrary characters in string
      */
     private static final String WILDCARD_CHARACTERS_REGEX = "\\*";
 
+    /**
+     * Regex for any number of arbitrary characters in string used in Java
+     */
+    private static final String WILDCARD_CHARACTERS_REGEX_JAVA = ".*";
+
     /**
      * Regex for finding punctuation at the start of word
      */
@@ -65,11 +68,6 @@ public class CatalogItemServiceImpl implements ICatalogItemService {
      */
     private static final Pattern END_PUNCTUATION_PATTERN = Pattern.compile(END_PUNCTUATION_REGEX);
 
-    /**
-     * Regex for any number of arbitrary characters in string used in SQL language
-     */
-    private static final String WILDCARD_CHARACTERS_REGEX_SQL = "%";
-
     /**
      * Message for exception when catalog item is not found by id
      */
@@ -125,18 +123,7 @@ public class CatalogItemServiceImpl implements ICatalogItemService {
         log.info("Catalog item deleted");
     }
 
-    @Override
-    public List<CatalogItemDto> getCatalog(String name, String country, String type) {
-        log.info("Retrieving catalog");
-        name = name.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_SQL);
-        name = name.replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_SQL);
-        country = country.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_SQL);
-        country = country.replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_SQL);
-        type = type.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_SQL);
-        type = type.replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_SQL);
-        Set<CatalogItem> entities = catalogItemRepository.filterCatalog(name, country, type);
-        return entities.stream().map(this::convertEntityToDto).collect(Collectors.toList());
-    }
+    private final Map<String, AlternativeName> map = new HashMap<>();
 
     @Override
     public CatalogItemDto getCatalogItem(UUID id) {
@@ -201,6 +188,32 @@ public class CatalogItemServiceImpl implements ICatalogItemService {
         return pathDto;
     }
 
+    @Override
+    public List<CatalogItemDto> getCatalog(String name, String country, String type, String writtenForm) {
+        log.info("Retrieving catalog");
+
+        String finalName = name.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
+        String finalCountry = country.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
+        String finalType = type.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
+        String finalWrittenForm = writtenForm.replaceAll(WILDCARD_CHARACTER_REGEX, WILDCARD_CHARACTER_REGEX_JAVA).replaceAll(WILDCARD_CHARACTERS_REGEX, WILDCARD_CHARACTERS_REGEX_JAVA);
+
+        Pattern patternName = Pattern.compile(finalName, Pattern.CASE_INSENSITIVE);
+        Pattern patternCountry = Pattern.compile(finalCountry, Pattern.CASE_INSENSITIVE);
+        Pattern patternType = Pattern.compile(finalType, Pattern.CASE_INSENSITIVE);
+        Pattern patternWrittenForm = Pattern.compile(finalWrittenForm, Pattern.CASE_INSENSITIVE);
+
+        List<CatalogItem> catalogItems = catalogItemRepository.findAll();
+
+        Predicate<CatalogItem> predicateType = i -> finalType.equals("") || i.getTypes().stream().anyMatch(t -> patternType.matcher(t.getType()).matches());
+        Predicate<CatalogItem> predicateCountry = i -> finalCountry.equals("") || i.getCountries().stream().anyMatch(t -> patternCountry.matcher(t.getName()).matches());
+        Predicate<CatalogItem> predicateName = i -> finalName.equals("") || patternName.matcher(i.getName()).matches() || i.getAlternativeNames().stream().anyMatch(t -> patternName.matcher(t.getName()).matches());
+        Predicate<CatalogItem> predicateWrittenForm = i -> finalWrittenForm.equals("") || i.getWrittenForms().stream().anyMatch(t -> patternWrittenForm.matcher(t.getForm()).matches());
+
+        catalogItems = catalogItems.stream().filter(predicateName.and(predicateCountry).and(predicateType).and(predicateWrittenForm)).collect(Collectors.toList());
+
+        return catalogItems.stream().map(this::convertEntityToDto).collect(Collectors.toList());
+    }
+
     /**
      * Saves catalog entity to database
      *
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogItemService.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogItemService.java
index a9a5bce..b661a0f 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogItemService.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogItemService.java
@@ -41,12 +41,13 @@ public interface ICatalogItemService {
     /**
      * Returns catalog items satisfying given filter
      *
-     * @param name    name - optional
-     * @param country country - optional
-     * @param type    type - optional
+     * @param name        name - optional
+     * @param country     country - optional
+     * @param type        type - optional
+     * @param writtenForm written form - optional
      * @return list of catalog items satisfying given filter
      */
-    List<CatalogItemDto> getCatalog(String name, String country, String type);
+    List<CatalogItemDto> getCatalog(String name, String country, String type, String writtenForm);
 
     /**
      * Returns catalog item with given ID
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/country/Country.java b/backend/src/main/java/cz/zcu/kiv/backendapi/country/Country.java
index 8960ee6..5415f95 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/country/Country.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/country/Country.java
@@ -1,31 +1,32 @@
 package cz.zcu.kiv.backendapi.country;
 
 import cz.zcu.kiv.backendapi.catalog.CatalogItem;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
 
 import javax.persistence.*;
-import java.io.Serializable;
 
 /**
  * Country entity representing country of catalog item
  */
-@Data
-@EqualsAndHashCode(exclude = "catalogItem")
-@ToString(exclude = "catalogItem")
+@Getter
+@Setter
 @NoArgsConstructor
 @AllArgsConstructor
 @Entity
 @Table(name = "countries")
-@IdClass(Country.class)
-public class Country implements Serializable {
+@IdClass(CountryPK.class)
+public class Country {
     /**
      * Name of country, serves as ID
      */
     @Id
     private String name;
 
-    @ManyToOne
-    @JoinColumn(name = "catalog_item_id")
+    @ManyToOne(fetch = FetchType.LAZY)
     @Id
+    @JoinColumn(name = "catalog_item_id")
     private CatalogItem catalogItem;
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryPK.java b/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryPK.java
new file mode 100644
index 0000000..6477270
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryPK.java
@@ -0,0 +1,26 @@
+package cz.zcu.kiv.backendapi.country;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+/**
+ * Class representing country primary key
+ */
+@EqualsAndHashCode
+@AllArgsConstructor
+@NoArgsConstructor
+public class CountryPK implements Serializable {
+    /**
+     * Name
+     */
+    private String name;
+
+    /**
+     * ID of catalog item
+     */
+    private UUID catalogItem;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenForm.java b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenForm.java
index a5124b5..ea28745 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenForm.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenForm.java
@@ -1,31 +1,32 @@
 package cz.zcu.kiv.backendapi.writtenform;
 
 import cz.zcu.kiv.backendapi.catalog.CatalogItem;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
 
 import javax.persistence.*;
-import java.io.Serializable;
 
 /**
  * Written form entity representing written form of catalog item
  */
-@Data
-@EqualsAndHashCode(exclude = "catalogItem")
-@ToString(exclude = "catalogItem")
+@Getter
+@Setter
 @NoArgsConstructor
 @AllArgsConstructor
 @Entity
 @Table(name = "written_forms")
-@IdClass(WrittenForm.class)
-public class WrittenForm implements Serializable {
+@IdClass(WrittenFormPK.class)
+public class WrittenForm {
     /**
      * Written form, serves as ID
      */
     @Id
     private String form;
 
-    @ManyToOne
-    @JoinColumn(name = "catalog_item_id")
+    @ManyToOne(fetch = FetchType.LAZY)
     @Id
+    @JoinColumn(name = "catalog_item_id")
     private CatalogItem catalogItem;
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormPK.java b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormPK.java
new file mode 100644
index 0000000..42c7f0b
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormPK.java
@@ -0,0 +1,26 @@
+package cz.zcu.kiv.backendapi.writtenform;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+/**
+ * Class representing written form primary key
+ */
+@EqualsAndHashCode
+@AllArgsConstructor
+@NoArgsConstructor
+public class WrittenFormPK implements Serializable {
+    /**
+     * Form
+     */
+    private String form;
+
+    /**
+     * ID of catalog item
+     */
+    private UUID catalogItem;
+}
\ No newline at end of file
diff --git a/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepositoryTest.java b/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepositoryTest.java
index 3d32d7b..3ed4930 100644
--- a/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepositoryTest.java
+++ b/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemRepositoryTest.java
@@ -1,9 +1,6 @@
 package cz.zcu.kiv.backendapi.catalog;
 
 import cz.zcu.kiv.backendapi.alternativename.AlternativeName;
-import cz.zcu.kiv.backendapi.country.Country;
-import cz.zcu.kiv.backendapi.type.Type;
-import cz.zcu.kiv.backendapi.type.TypeRepository;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -22,9 +19,6 @@ class CatalogItemRepositoryTest {
     @Autowired
     private CatalogItemRepository underTest;
 
-    @Autowired
-    private TypeRepository typeRepository;
-
     private CatalogItem catalogItem1;
     private CatalogItem catalogItem2;
     private CatalogItem catalogItem3;
@@ -33,13 +27,6 @@ class CatalogItemRepositoryTest {
 
     @BeforeEach
     void setUp() {
-        Type typeCountry = new Type("country");
-        Type typeCity = new Type("city");
-        Type typeCapitalCity = new Type("capital city new");
-        Type typeCityUpper = new Type("City");
-        Type typeCountri = new Type("countri");
-        typeRepository.saveAll(List.of(typeCountry, typeCity, typeCapitalCity, typeCityUpper, typeCountri));
-
         String nameFirst = "first";
         String nameFirstUpper = "First";
         String nameSecond = "second";
@@ -48,14 +35,6 @@ class CatalogItemRepositoryTest {
         String nameTwelve = "twelve";
         String nameTwentyUpper = "TWENTY";
 
-        String countryAaa = "aaa";
-        String countryAaaUpper = "AAA";
-        String countryBbb = "bbb";
-        String countryBccb = "bccb";
-        String countryCcc = "ccc";
-        String countryDdd = "ddd";
-        String countryDcd = "dcd";
-
         catalogItem1 = new CatalogItem();
         catalogItem2 = new CatalogItem();
         catalogItem3 = new CatalogItem();
@@ -63,28 +42,17 @@ class CatalogItemRepositoryTest {
         catalogItem5 = new CatalogItem();
 
         catalogItem1.setName(nameFirst);
-        catalogItem1.setTypes(Set.of(typeCountry, typeCity));
-        catalogItem1.setCountries(Set.of(new Country(countryAaa, catalogItem1), new Country(countryDcd, catalogItem1)));
 
         catalogItem2.setName(nameSecond);
         catalogItem2.setAlternativeNames(Set.of(new AlternativeName(nameTwelve, catalogItem2), new AlternativeName(nameThird, catalogItem2)));
-        catalogItem2.setTypes(Set.of(typeCountry, typeCityUpper));
-        catalogItem2.setCountries(Set.of(new Country(countryAaa, catalogItem2), new Country(countryBbb, catalogItem2)));
 
         catalogItem3.setName(nameThird);
         catalogItem3.setAlternativeNames(Set.of(new AlternativeName(nameTwentyUpper, catalogItem3), new AlternativeName(nameSedond, catalogItem3)));
-        catalogItem3.setTypes(Set.of(typeCountri, typeCapitalCity));
-        catalogItem3.setCountries(Set.of(new Country(countryAaaUpper, catalogItem3), new Country(countryCcc, catalogItem3)));
-
 
         catalogItem4.setAlternativeNames(Set.of(new AlternativeName(nameTwelve, catalogItem4), new AlternativeName(nameFirstUpper, catalogItem4)));
-        catalogItem4.setTypes(Set.of(typeCountri, typeCountry));
-        catalogItem4.setCountries(Set.of(new Country(countryBccb, catalogItem4), new Country(countryDdd, catalogItem4)));
-
 
         catalogItem5.setName(nameSedond);
         catalogItem5.setAlternativeNames(Set.of(new AlternativeName(nameThird, catalogItem5)));
-        catalogItem5.setTypes(Set.of(typeCountri));
 
         underTest.saveAll(List.of(catalogItem1, catalogItem2, catalogItem3, catalogItem4, catalogItem5));
 
@@ -96,234 +64,6 @@ class CatalogItemRepositoryTest {
         underTest.deleteAll();
     }
 
-    @Test
-    void itShouldReturnAll() {
-        // given
-        String name = "";
-        String country = "";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(5);
-    }
-
-    @Test
-    void testName() {
-        // given
-        String name = "first";
-        String country = "";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(2);
-        assertTrue(filterResult.contains(catalogItem1));
-        assertTrue(filterResult.contains(catalogItem4));
-    }
-
-    @Test
-    void testWildcardCharacterName() {
-        // given
-        String name = "se_ond";
-        String country = "";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(3);
-        assertTrue(filterResult.contains(catalogItem2));
-        assertTrue(filterResult.contains(catalogItem3));
-        assertTrue(filterResult.contains(catalogItem5));
-    }
-
-    @Test
-    void testWildcardCharactersName() {
-        // given
-        String name = "twe%";
-        String country = "";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(3);
-        assertTrue(filterResult.contains(catalogItem2));
-        assertTrue(filterResult.contains(catalogItem3));
-        assertTrue(filterResult.contains(catalogItem4));
-    }
-
-    @Test
-    void testCountry() {
-        // given
-        String name = "";
-        String country = "aaa";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(3);
-        assertTrue(filterResult.contains(catalogItem1));
-        assertTrue(filterResult.contains(catalogItem2));
-        assertTrue(filterResult.contains(catalogItem3));
-    }
-
-    @Test
-    void testWildcardCharacterCountry() {
-        // given
-        String name = "";
-        String country = "d_d";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(2);
-        assertTrue(filterResult.contains(catalogItem1));
-        assertTrue(filterResult.contains(catalogItem4));
-    }
-
-    @Test
-    void testWildcardCharactersCountry() {
-        // given
-        String name = "";
-        String country = "b%b";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(2);
-        assertTrue(filterResult.contains(catalogItem2));
-        assertTrue(filterResult.contains(catalogItem4));
-    }
-
-
-    @Test
-    void testType() {
-        // given
-        String name = "";
-        String country = "";
-        String type = "city";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(2);
-        assertTrue(filterResult.contains(catalogItem1));
-        assertTrue(filterResult.contains(catalogItem2));
-    }
-
-    @Test
-    void testWildcardCharacterType() {
-        // given
-        String name = "";
-        String country = "";
-        String type = "countr_";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(5);
-        assertTrue(filterResult.contains(catalogItem1));
-        assertTrue(filterResult.contains(catalogItem2));
-        assertTrue(filterResult.contains(catalogItem3));
-        assertTrue(filterResult.contains(catalogItem4));
-        assertTrue(filterResult.contains(catalogItem5));
-    }
-
-    @Test
-    void testWildcardCharactersType() {
-        // given
-        String name = "";
-        String country = "";
-        String type = "%city%";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(3);
-        assertTrue(filterResult.contains(catalogItem1));
-        assertTrue(filterResult.contains(catalogItem2));
-        assertTrue(filterResult.contains(catalogItem3));
-    }
-
-    @Test
-    void testNameAndCountry() {
-        // given
-        String name = "third";
-        String country = "aaa";
-        String type = "";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(2);
-        assertTrue(filterResult.contains(catalogItem2));
-        assertTrue(filterResult.contains(catalogItem3));
-    }
-
-    @Test
-    void testNameAndType() {
-        // given
-        String name = "third";
-        String country = "";
-        String type = "countri";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(2);
-        assertTrue(filterResult.contains(catalogItem3));
-        assertTrue(filterResult.contains(catalogItem5));
-    }
-
-    @Test
-    void testCountryAndType() {
-        // given
-        String name = "";
-        String country = "ddd";
-        String type = "country";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(1);
-        assertTrue(filterResult.contains(catalogItem4));
-    }
-
-    @Test
-    void testAll() {
-        // given
-        String name = "third";
-        String country = "AAA";
-        String type = "countri";
-
-        // when
-        Set<CatalogItem> filterResult = underTest.filterCatalog(name, country, type);
-
-        // then
-        assertThat(filterResult.size()).isEqualTo(1);
-        assertTrue(filterResult.contains(catalogItem3));
-    }
-
     @Test
     void testItemsByName() {
         // given
diff --git a/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest.java b/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest.java
index 1f32a19..9d75dc9 100644
--- a/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest.java
+++ b/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest.java
@@ -21,7 +21,6 @@ import java.util.stream.Stream;
 
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.BDDMockito.given;
@@ -37,7 +36,6 @@ class CatalogItemServiceImplTest {
     @Mock
     private TypeServiceImpl typeService;
 
-
     private CatalogItemServiceImpl underTest;
 
     @BeforeEach
@@ -127,7 +125,16 @@ class CatalogItemServiceImplTest {
 
         CatalogItem capturedItem = argumentCaptor.getValue();
 
-        assertThat(capturedItem).isEqualTo(catalogItem);
+        assertThat(capturedItem.getName()).isEqualTo(catalogItem.getName());
+        assertThat(capturedItem.getLongitude()).isEqualTo(catalogItem.getLongitude());
+        assertThat(capturedItem.getLatitude()).isEqualTo(catalogItem.getLatitude());
+        assertThat(capturedItem.getCertainty()).isEqualTo(catalogItem.getCertainty());
+        assertThat(capturedItem.getAlternativeNames().size()).isEqualTo(catalogItem.getAlternativeNames().size());
+        assertThat(capturedItem.getBibliography().size()).isEqualTo(catalogItem.getBibliography().size());
+        assertThat(capturedItem.getCountries().size()).isEqualTo(catalogItem.getCountries().size());
+        assertThat(capturedItem.getWrittenForms().size()).isEqualTo(catalogItem.getWrittenForms().size());
+        assertThat(capturedItem.getTypes().size()).isEqualTo(catalogItem.getTypes().size());
+        assertThat(capturedItem.getDescription()).isEqualTo(catalogItem.getDescription());
 
     }
 
@@ -184,6 +191,7 @@ class CatalogItemServiceImplTest {
         Type typeOld = new Type("old");
 
         CatalogItem catalogItem = new CatalogItem();
+        catalogItem.setId(id);
         catalogItem.setName("name");
         catalogItem.setBibliography(Set.of(new Bibliography("bibl", catalogItem)));
         catalogItem.setTypes(Set.of(type));
@@ -196,6 +204,7 @@ class CatalogItemServiceImplTest {
         catalogItem.setDescription("description");
 
         CatalogItem oldCatalogItem = new CatalogItem();
+        oldCatalogItem.setId(id);
         oldCatalogItem.setName("old");
         oldCatalogItem.setBibliography(Set.of(new Bibliography("old", oldCatalogItem)));
         oldCatalogItem.setTypes(Set.of(typeOld));
@@ -279,74 +288,7 @@ class CatalogItemServiceImplTest {
         verify(catalogItemRepository, never()).deleteById(any());
     }
 
-    @Test
-    void getCatalog() {
-        // given
-        String name = "aaa?bb*aa";
-        String country = "aaa?bb*aa";
-        String type = "aaa?bb*aa";
-        String nameChanged = "aaa_bb%aa";
-        String countryChanged = "aaa_bb%aa";
-        String typeChanged = "aaa_bb%aa";
-
-        Type typeEntity = new Type(type);
-
-        CatalogItem catalogItem = new CatalogItem();
-        catalogItem.setName("aaacbbbbbbbaa");
-        catalogItem.setBibliography(Set.of(new Bibliography("bibl", catalogItem)));
-        catalogItem.setTypes(Set.of(typeEntity));
-        catalogItem.setAlternativeNames(Set.of(new AlternativeName("altName", catalogItem)));
-        catalogItem.setCountries(Set.of(new Country("aaaabbaa", catalogItem)));
-        catalogItem.setWrittenForms(Set.of(new WrittenForm("written", catalogItem)));
-        catalogItem.setCertainty(0);
-        catalogItem.setLatitude(0.1);
-        catalogItem.setLongitude(0.2);
-
-        CatalogItem catalogItem2 = new CatalogItem();
-        catalogItem2.setName("name");
-        catalogItem2.setBibliography(Set.of(new Bibliography("bibl", catalogItem2)));
-        catalogItem2.setTypes(Set.of(typeEntity));
-        catalogItem2.setAlternativeNames(Set.of(new AlternativeName("aaaabbbbbbaa", catalogItem2)));
-        catalogItem2.setCountries(Set.of(new Country("aaaabbcccefaa", catalogItem2)));
-        catalogItem2.setWrittenForms(Set.of(new WrittenForm("written", catalogItem2)));
-        catalogItem2.setCertainty(1);
-        catalogItem2.setLatitude(1.1);
-        catalogItem2.setLongitude(1.2);
-
-        CatalogItemDto catalogItemDto = new CatalogItemDto();
-        catalogItemDto.setName("aaacbbbbbbbaa");
-        catalogItemDto.setBibliography(Set.of("bibl"));
-        catalogItemDto.setTypes(Set.of("aaa?bb*aa"));
-        catalogItemDto.setAlternativeNames(Set.of("altName"));
-        catalogItemDto.setCountries(Set.of("aaaabbaa"));
-        catalogItemDto.setWrittenForms(Set.of("written"));
-        catalogItemDto.setCertainty(0);
-        catalogItemDto.setLatitude(0.1);
-        catalogItemDto.setLongitude(0.2);
-
-        CatalogItemDto catalogItemDto2 = new CatalogItemDto();
-        catalogItemDto2.setName("name");
-        catalogItemDto2.setBibliography(Set.of("bibl"));
-        catalogItemDto2.setTypes(Set.of("aaa?bb*aa"));
-        catalogItemDto2.setAlternativeNames(Set.of("aaaabbbbbbaa"));
-        catalogItemDto2.setCountries(Set.of("aaaabbcccefaa"));
-        catalogItemDto2.setWrittenForms(Set.of("written"));
-        catalogItemDto2.setCertainty(1);
-        catalogItemDto2.setLatitude(1.1);
-        catalogItemDto2.setLongitude(1.2);
-
-        given(catalogItemRepository.filterCatalog(nameChanged, countryChanged, typeChanged)).willReturn(Set.of(catalogItem, catalogItem2));
-
-        // when
-        List<CatalogItemDto> results = underTest.getCatalog(name, country, type);
 
-        // then
-        assertThat(results.size()).isEqualTo(2);
-        assertTrue(results.contains(catalogItemDto));
-        assertTrue(results.contains(catalogItemDto2));
-
-        verify(catalogItemRepository).filterCatalog(nameChanged, countryChanged, typeChanged);
-    }
 
     @Test
     void testSearchedTest() {
@@ -389,31 +331,37 @@ class CatalogItemServiceImplTest {
         catalogItem6.setLongitude(0.0);
 
         CatalogItemDto catalogItemDto1 = new CatalogItemDto();
+        catalogItemDto1.setId(catalogItem1.getId());
         catalogItemDto1.setAlternativeNames(Stream.of("Azbar").collect(Collectors.toSet()));
         catalogItemDto1.setLatitude(5);
         catalogItemDto1.setLongitude(5);
 
         CatalogItemDto catalogItemDto2 = new CatalogItemDto();
+        catalogItemDto2.setId(catalogItem2.getId());
         catalogItemDto2.setAlternativeNames(Stream.of("Azbar", "Azbarasdf").collect(Collectors.toSet()));
         catalogItemDto2.setLatitude(0.0);
         catalogItemDto2.setLongitude(0.0);
 
         CatalogItemDto catalogItemDto3 = new CatalogItemDto();
+        catalogItemDto3.setId(catalogItem3.getId());
         catalogItemDto3.setAlternativeNames(Stream.of("U-re-me-re").collect(Collectors.toSet()));
         catalogItemDto3.setLatitude(55);
         catalogItemDto3.setLongitude(68);
 
         CatalogItemDto catalogItemDto4 = new CatalogItemDto();
+        catalogItemDto4.setId(catalogItem4.getId());
         catalogItemDto4.setAlternativeNames(Stream.of("Huga").collect(Collectors.toSet()));
         catalogItemDto4.setLatitude(0.0);
         catalogItemDto4.setLongitude(0.0);
 
         CatalogItemDto catalogItemDto5 = new CatalogItemDto();
+        catalogItemDto5.setId(catalogItem5.getId());
         catalogItemDto5.setAlternativeNames(Stream.of("Huga", "Hugaa").collect(Collectors.toSet()));
         catalogItemDto5.setLatitude(0.0);
         catalogItemDto5.setLongitude(0.0);
 
         CatalogItemDto catalogItemDto6 = new CatalogItemDto();
+        catalogItemDto6.setId(catalogItem6.getId());
         catalogItemDto6.setAlternativeNames(Stream.of("Duga").collect(Collectors.toSet()));
         catalogItemDto6.setLatitude(0.0);
         catalogItemDto6.setLongitude(0.0);
diff --git a/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest2.java b/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest2.java
new file mode 100644
index 0000000..8e32a25
--- /dev/null
+++ b/backend/src/test/java/cz/zcu/kiv/backendapi/catalog/CatalogItemServiceImplTest2.java
@@ -0,0 +1,474 @@
+package cz.zcu.kiv.backendapi.catalog;
+
+import cz.zcu.kiv.backendapi.alternativename.AlternativeName;
+import cz.zcu.kiv.backendapi.country.Country;
+import cz.zcu.kiv.backendapi.type.Type;
+import cz.zcu.kiv.backendapi.type.TypeServiceImpl;
+import cz.zcu.kiv.backendapi.writtenform.WrittenForm;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+class CatalogItemServiceImplTest2 {
+    @Mock
+    private CatalogItemRepository catalogItemRepository;
+
+    @Mock
+    private TypeServiceImpl typeService;
+
+    private CatalogItemServiceImpl underTest;
+
+    private CatalogItemDto catalogItemDto1;
+    private CatalogItemDto catalogItemDto2;
+    private CatalogItemDto catalogItemDto3;
+    private CatalogItemDto catalogItemDto4;
+    private CatalogItemDto catalogItemDto5;
+
+    @BeforeEach
+    void setUp() {
+        underTest = new CatalogItemServiceImpl(catalogItemRepository, typeService);
+        // given
+        String country = "country";
+        String city = "city";
+        String capitalCityNew = "capital city new";
+        String cityUpper = "City";
+        String countri = "countri";
+
+        Type typeCountry = new Type(country);
+        Type typeCity = new Type(city);
+        Type typeCapitalCity = new Type(capitalCityNew);
+        Type typeCityUpper = new Type(cityUpper);
+        Type typeCountri = new Type(countri);
+
+        String nameFirst = "first";
+        String nameFirstUpper = "First";
+        String nameSecond = "second";
+        String nameSedond = "sedond";
+        String nameThird = "third";
+        String nameTwelve = "twelve";
+        String nameTwentyUpper = "TWENTY";
+
+        String countryAaa = "aaa";
+        String countryAaaUpper = "AAA";
+        String countryBbb = "bbb";
+        String countryBccb = "bccb";
+        String countryCcc = "ccc";
+        String countryDdd = "ddd";
+        String countryDcd = "dcd";
+
+        String writtenForm = "written";
+        String writtenFormUpper = "WRITTEN";
+        String writtenFormForOr = "wratten";
+
+        CatalogItem catalogItem1 = new CatalogItem();
+        CatalogItem catalogItem2 = new CatalogItem();
+        CatalogItem catalogItem3 = new CatalogItem();
+        CatalogItem catalogItem4 = new CatalogItem();
+        CatalogItem catalogItem5 = new CatalogItem();
+
+        UUID catalogItemId1 = UUID.randomUUID();
+        UUID catalogItemId2 = UUID.randomUUID();
+        UUID catalogItemId3 = UUID.randomUUID();
+        UUID catalogItemId4 = UUID.randomUUID();
+        UUID catalogItemId5 = UUID.randomUUID();
+
+        catalogItem1.setId(catalogItemId1);
+        catalogItem2.setId(catalogItemId2);
+        catalogItem3.setId(catalogItemId3);
+        catalogItem4.setId(catalogItemId4);
+        catalogItem5.setId(catalogItemId5);
+
+        catalogItem1.setName(nameFirst);
+        catalogItem1.setTypes(Set.of(typeCountry, typeCity));
+        catalogItem1.setCountries(Set.of(new Country(countryAaa, catalogItem1), new Country(countryDcd, catalogItem1)));
+        catalogItem1.setWrittenForms(Set.of(new WrittenForm(writtenForm, catalogItem1)));
+
+        catalogItemDto1 = new CatalogItemDto(catalogItemId1, nameFirst, Collections.emptySet(), Set.of(writtenForm), Set.of(country, city), Set.of(countryAaa, countryDcd), Collections.emptySet(), 0.0, 0.0, 0, "");
+
+        catalogItem2.setName(nameSecond);
+        catalogItem2.setAlternativeNames(Set.of(new AlternativeName(nameTwelve, catalogItem2), new AlternativeName(nameThird, catalogItem2)));
+        catalogItem2.setTypes(Set.of(typeCountry, typeCityUpper));
+        catalogItem2.setCountries(Set.of(new Country(countryAaa, catalogItem2), new Country(countryBbb, catalogItem2)));
+        catalogItem2.setWrittenForms(Set.of(new WrittenForm(writtenFormUpper, catalogItem2)));
+
+        catalogItemDto2 = new CatalogItemDto(catalogItemId2, nameSecond, Set.of(nameTwelve, nameThird), Set.of(writtenFormUpper), Set.of(country, cityUpper), Set.of(countryAaa, countryBbb), Collections.emptySet(), 0.0, 0.0, 0, "");
+
+        catalogItem3.setName(nameThird);
+        catalogItem3.setAlternativeNames(Set.of(new AlternativeName(nameTwentyUpper, catalogItem3), new AlternativeName(nameSedond, catalogItem3)));
+        catalogItem3.setTypes(Set.of(typeCountri, typeCapitalCity));
+        catalogItem3.setCountries(Set.of(new Country(countryAaaUpper, catalogItem3), new Country(countryCcc, catalogItem3)));
+        catalogItem3.setWrittenForms(Set.of(new WrittenForm(writtenFormForOr, catalogItem3)));
+
+        catalogItemDto3 = new CatalogItemDto(catalogItemId3, nameThird, Set.of(nameTwentyUpper, nameSedond), Set.of(writtenFormForOr), Set.of(countri, capitalCityNew), Set.of(countryAaaUpper, countryCcc), Collections.emptySet(), 0.0, 0.0, 0, "");
+
+        catalogItem4.setAlternativeNames(Set.of(new AlternativeName(nameTwelve, catalogItem4), new AlternativeName(nameFirstUpper, catalogItem4)));
+        catalogItem4.setTypes(Set.of(typeCountri, typeCountry));
+        catalogItem4.setCountries(Set.of(new Country(countryBccb, catalogItem4), new Country(countryDdd, catalogItem4)));
+        catalogItem4.setWrittenForms(Set.of(new WrittenForm(writtenForm, catalogItem4), new WrittenForm(writtenFormForOr, catalogItem4)));
+
+        catalogItemDto4 = new CatalogItemDto(catalogItemId4, "", Set.of(nameTwelve, nameFirstUpper), Set.of(writtenForm, writtenFormForOr), Set.of(countri, country), Set.of(countryBccb, countryDdd), Collections.emptySet(), 0.0, 0.0, 0, "");
+
+        catalogItem5.setName(nameSedond);
+        catalogItem5.setAlternativeNames(Set.of(new AlternativeName(nameThird, catalogItem5)));
+        catalogItem5.setTypes(Set.of(typeCountri));
+
+        catalogItemDto5 = new CatalogItemDto(catalogItemId5, nameSedond, Set.of(nameThird), Collections.emptySet(), Set.of(countri), Collections.emptySet(), Collections.emptySet(), 0.0, 0.0, 0, "");
+
+        given(catalogItemRepository.findAll()).willReturn(List.of(catalogItem1, catalogItem2, catalogItem3, catalogItem4, catalogItem5));
+    }
+
+    @Test
+    void itShouldReturnAll() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> results = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(results.size()).isEqualTo(5);
+        assertTrue(results.contains(catalogItemDto1));
+        assertTrue(results.contains(catalogItemDto2));
+        assertTrue(results.contains(catalogItemDto3));
+        assertTrue(results.contains(catalogItemDto4));
+        assertTrue(results.contains(catalogItemDto5));
+
+        verify(catalogItemRepository).findAll();
+    }
+
+    @Test
+    void testName() {
+        // given
+        String name = "first";
+        String country = "";
+        String type = "";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(2);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testWildcardCharacterName() {
+        // given
+        String name = "se?ond";
+        String country = "";
+        String type = "";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(3);
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+        assertTrue(filterResult.contains(catalogItemDto5));
+    }
+
+    @Test
+    void testWildcardCharactersName() {
+        // given
+        String name = "twe*";
+        String country = "";
+        String type = "";
+        String writtenForm = "";
+
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(3);
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testCountry() {
+        // given
+        String name = "";
+        String country = "aaa";
+        String type = "";
+        String writtenForm = "";
+
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(3);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+    }
+
+    @Test
+    void testWildcardCharacterCountry() {
+        // given
+        String name = "";
+        String country = "d?d";
+        String type = "";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(2);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testWildcardCharactersCountry() {
+        // given
+        String name = "";
+        String country = "b*b";
+        String type = "";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(2);
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+
+    @Test
+    void testType() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "city";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(2);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+    }
+
+    @Test
+    void testWildcardCharacterType() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "countr?";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(5);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+        assertTrue(filterResult.contains(catalogItemDto4));
+        assertTrue(filterResult.contains(catalogItemDto5));
+    }
+
+    @Test
+    void testWildcardCharactersType() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "*city*";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(3);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+    }
+
+    @Test
+    void testWrittenForm() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "";
+        String writtenForm = "written";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(3);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testWrittenFormWildcardCharacter() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "";
+        String writtenForm = "wr?tten";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(4);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testWrittenFormWildcardCharacters() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "";
+        String writtenForm = "wri*tten";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(3);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testWrittenFormOr() {
+        // given
+        String name = "";
+        String country = "";
+        String type = "";
+        String writtenForm = "wr(i|a)tten";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(4);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testNameAndCountry() {
+        // given
+        String name = "third";
+        String country = "aaa";
+        String type = "";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(2);
+        assertTrue(filterResult.contains(catalogItemDto2));
+        assertTrue(filterResult.contains(catalogItemDto3));
+    }
+
+    @Test
+    void testNameAndType() {
+        // given
+        String name = "third";
+        String country = "";
+        String type = "countri";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(2);
+        assertTrue(filterResult.contains(catalogItemDto3));
+        assertTrue(filterResult.contains(catalogItemDto5));
+    }
+
+    @Test
+    void testNameAndWrittenForm() {
+        // given
+        String name = "first";
+        String country = "";
+        String type = "";
+        String writtenForm = "written";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(2);
+        assertTrue(filterResult.contains(catalogItemDto1));
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testCountryAndType() {
+        // given
+        String name = "";
+        String country = "ddd";
+        String type = "country";
+        String writtenForm = "";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(1);
+        assertTrue(filterResult.contains(catalogItemDto4));
+    }
+
+    @Test
+    void testAll() {
+        // given
+        String name = "third";
+        String country = "AAA";
+        String type = "countri";
+        String writtenForm = "wratten";
+
+        // when
+        List<CatalogItemDto> filterResult = underTest.getCatalog(name, country, type, writtenForm);
+
+        // then
+        assertThat(filterResult.size()).isEqualTo(1);
+        assertTrue(filterResult.contains(catalogItemDto3));
+    }
+}
\ No newline at end of file
