From 178fb7be4b19eb2d44620a1d8c09c7ac515f9f9b Mon Sep 17 00:00:00 2001 From: Mykhailo Date: Wed, 8 Oct 2025 23:14:02 +0300 Subject: [PATCH 1/3] =?UTF-8?q?=D0=92=D0=B8=D0=BA=D0=BE=D0=BD=D0=B0=D0=BD?= =?UTF-8?q?=D1=96=20=D0=B7=D0=B0=D0=B2=D0=B4=D0=B0=D0=BD=D0=BD=D1=8F=20?= =?UTF-8?q?=D0=B7=20java-fundamentals-exercises?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/bobocode/intro/ExerciseIntroduction.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java b/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java index 35d925636..a3f320f45 100644 --- a/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java +++ b/0-0-intro/src/main/java/com/bobocode/intro/ExerciseIntroduction.java @@ -2,6 +2,8 @@ import com.bobocode.util.ExerciseNotCompletedException; +import java.util.Base64; + /** * Welcome! This is an introduction exercise that will show you a simple example of Bobocode exercises. *

@@ -24,7 +26,8 @@ public class ExerciseIntroduction { */ public String getWelcomeMessage() { // todo: implement a method and return a message according to javadoc - throw new ExerciseNotCompletedException(); + // throw new ExerciseNotCompletedException(); + return "The key to efficient learning is practice!"; } /** @@ -40,6 +43,7 @@ public String getWelcomeMessage() { */ public String encodeMessage(String message) { // todo: switch to branch "completed" in order to see how it should be implemented - throw new ExerciseNotCompletedException(); + // throw new ExerciseNotCompletedException(); + return Base64.getEncoder().encodeToString(message.getBytes()); } } From 3a295ebc164341e7cfb09b5d7d9fd995f3449662 Mon Sep 17 00:00:00 2001 From: Mykhailo Date: Thu, 9 Oct 2025 13:33:21 +0300 Subject: [PATCH 2/3] =?UTF-8?q?=D0=92=D0=B8=D0=BA=D0=BE=D0=BD=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=96=20=D0=B7=D0=B0=D0=B2=D0=B4=D0=B0=D0=BD=D0=BD=D1=8F?= =?UTF-8?q?=201-3-0,=201-3-1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/bobocode/basics/Box.java | 10 +- .../com/bobocode/basics/CrazyGenerics.java | 103 ++++++++++++------ 2 files changed, 75 insertions(+), 38 deletions(-) diff --git a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java index 5a2d860ee..180603a28 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/Box.java @@ -7,18 +7,18 @@ *

* todo: refactor this class so it uses generic type "T" and run {@link com.bobocode.basics.BoxTest} to verify it */ -public class Box { - private Object value; +public class Box { + private T value; - public Box(Object value) { + public Box(T value) { this.value = value; } - public Object getValue() { + public T getValue() { return value; } - public void setValue(Object value) { + public void setValue(T value) { this.value = value; } } diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java index 751d5899f..79b693960 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java @@ -5,10 +5,8 @@ import lombok.Data; import java.io.Serializable; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.function.Predicate; /** * {@link CrazyGenerics} is an exercise class. It consists of classes, interfaces and methods that should be updated @@ -33,8 +31,8 @@ public class CrazyGenerics { * @param – value type */ @Data - public static class Sourced { // todo: refactor class to introduce type parameter and make value generic - private Object value; + public static class Sourced { // todo: refactor class to introduce type parameter and make value generic + private T value; private String source; } @@ -45,11 +43,11 @@ public static class Sourced { // todo: refactor class to introduce type paramete * @param – actual, min and max type */ @Data - public static class Limited { + public static class Limited { // todo: refactor class to introduce type param bounded by number and make fields generic numbers - private final Object actual; - private final Object min; - private final Object max; + private final T actual; + private final T min; + private final T max; } /** @@ -59,8 +57,9 @@ public static class Limited { * @param – source object type * @param - converted result type */ - public interface Converter { // todo: introduce type parameters + public interface Converter { // todo: introduce type parameters // todo: add convert method + R convert(T obj); } /** @@ -70,10 +69,10 @@ public interface Converter { // todo: introduce type parameters * * @param – value type */ - public static class MaxHolder { // todo: refactor class to make it generic - private Object max; + public static class MaxHolder> { // todo: refactor class to make it generic + private T max; - public MaxHolder(Object max) { + public MaxHolder(T max) { this.max = max; } @@ -82,11 +81,14 @@ public MaxHolder(Object max) { * * @param val a new value */ - public void put(Object val) { - throw new ExerciseNotCompletedException(); // todo: update parameter and implement the method + public void put(T val) { + // throw new ExerciseNotCompletedException(); // todo: update parameter and implement the method + if(val.compareTo(max) > 0){ + max = val; + } } - public Object getMax() { + public T getMax() { return max; } } @@ -97,8 +99,8 @@ public Object getMax() { * * @param – the type of objects that can be processed */ - interface StrictProcessor { // todo: make it generic - void process(Object obj); + interface StrictProcessor> { // todo: make it generic + void process(T obj); } /** @@ -108,10 +110,9 @@ interface StrictProcessor { // todo: make it generic * @param – a type of the entity that should be a subclass of {@link BaseEntity} * @param – a type of any collection */ - interface CollectionRepository { // todo: update interface according to the javadoc - void save(Object entity); - - Collection getEntityCollection(); + interface CollectionRepository> { // todo: update interface according to the javadoc + void save(T entity); + C getEntityCollection(); } /** @@ -120,7 +121,7 @@ interface CollectionRepository { // todo: update interface according to the java * * @param – a type of the entity that should be a subclass of {@link BaseEntity} */ - interface ListRepository { // todo: update interface according to the javadoc + interface ListRepository extends CollectionRepository> { // todo: update interface according to the javadoc } /** @@ -133,7 +134,11 @@ interface ListRepository { // todo: update interface according to the javadoc * * @param a type of collection elements */ - interface ComparableCollection { // todo: refactor it to make generic and provide a default impl of compareTo + interface ComparableCollection extends Collection, Comparable> { // todo: refactor it to make generic and provide a default impl of compareTo + @Override + default int compareTo(Collection o){ + return Integer.compare(this.size(), o.size()) + } } /** @@ -147,7 +152,7 @@ static class CollectionUtil { * * @param list */ - public static void print(List list) { + public static void print(List list) { // todo: refactor it so the list of any type can be printed, not only integers list.forEach(element -> System.out.println(" – " + element)); } @@ -160,8 +165,10 @@ public static void print(List list) { * @param entities provided collection of entities * @return true if at least one of the elements has null id */ - public static boolean hasNewEntities(Collection entities) { - throw new ExerciseNotCompletedException(); // todo: refactor parameter and implement method + public static boolean hasNewEntities(Collection entities) { + //throw new ExerciseNotCompletedException(); // todo: refactor parameter and implement method + return entities.stream() + .anyMatch(e -> e.getUuid() == null); } /** @@ -173,8 +180,10 @@ public static boolean hasNewEntities(Collection entities) { * @param validationPredicate criteria for validation * @return true if all entities fit validation criteria */ - public static boolean isValidCollection() { - throw new ExerciseNotCompletedException(); // todo: add method parameters and implement the logic + public static boolean isValidCollection(Collection entities, Predicate validationPredicate) { + //throw new ExerciseNotCompletedException(); // todo: add method parameters and implement the logic + return entities.stream() + .allMatch(validationPredicate); } /** @@ -187,8 +196,11 @@ public static boolean isValidCollection() { * @param entity type * @return true if entities list contains target entity more than once */ - public static boolean hasDuplicates() { - throw new ExerciseNotCompletedException(); // todo: update method signature and implement it + public static boolean hasDuplicates(Collection entities, T targetEntity) { + //throw new ExerciseNotCompletedException(); // todo: update method signature and implement it + return entities.stream() + .filter(e -> e.getUuid().equals(targetEntity.getUuid())) + .count() > 1; } /** @@ -201,6 +213,20 @@ public static boolean hasDuplicates() { * @return optional max value */ // todo: create a method and implement its logic manually without using util method from JDK + public static Optional findMax(Iterable elements, Comparator comparator){ + var iterator = elements.iterator(); + if(!iterator.hasNext()){ + return Optional.empty(); + } + var max = iterator.next(); + while(iterator.hasNext()){ + var element = iterator.next(); + if(comparator.compare(element, max) > 0){ + max = element; + } + } + return Optional.of(max); + } /** * findMostRecentlyCreatedEntity is a generic util method that accepts a collection of entities and returns the @@ -215,6 +241,10 @@ public static boolean hasDuplicates() { * @return an entity from the given collection that has the max createdOn value */ // todo: create a method according to JavaDoc and implement it using previous method + public static T findMostRecentlyCreatedEntity(Collection entities){ + return findMax(entities, CREATED_ON_COMPARATOR) + .orElseThrow(); + } /** * An util method that allows to swap two elements of any list. It changes the list so the element with the index @@ -228,7 +258,14 @@ public static boolean hasDuplicates() { public static void swap(List elements, int i, int j) { Objects.checkIndex(i, elements.size()); Objects.checkIndex(j, elements.size()); - throw new ExerciseNotCompletedException(); // todo: complete method implementation + //throw new ExerciseNotCompletedException(); // todo: complete method implementation + swapHelper(elements, i, j); + } + + private static void swapHelper(List elements, int i, int j){ + T temp = elements.get(i); + elements.set(i, elements.get(j)); + elements.set(j, temp); } } From 3c127b4916929663162592d0fa19993d6e8def0d Mon Sep 17 00:00:00 2001 From: Mykhailo Date: Tue, 9 Dec 2025 19:05:57 +0200 Subject: [PATCH 3/3] =?UTF-8?q?=D0=9E=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=BA=D0=BE=D0=B4=201-3-1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bobocode/basics/CrazyGenerics.java | 544 +++++++++--------- 1 file changed, 272 insertions(+), 272 deletions(-) diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java index 79b693960..d367c44c2 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/CrazyGenerics.java @@ -1,272 +1,272 @@ -package com.bobocode.basics; - -import com.bobocode.basics.util.BaseEntity; -import com.bobocode.util.ExerciseNotCompletedException; -import lombok.Data; - -import java.io.Serializable; -import java.util.*; -import java.util.function.Predicate; - -/** - * {@link CrazyGenerics} is an exercise class. It consists of classes, interfaces and methods that should be updated - * using generics. - *

- * TODO: go step by step from top to bottom. Read the java doc, write code and run CrazyGenericsTest to verify your impl - *

- * Hint: in some cases you will need to refactor the code, like replace {@link Object} with a generic type. In order - * cases you will need to add new fields, create new classes, or add new methods. Always try to read java doc and update - * the code according to it. - *

- * TODO: to get the most out of your learning, visit our website - *

- * - * @author Taras Boychuk - */ -public class CrazyGenerics { - /** - * {@link Sourced} is a container class that allows storing any object along with the source of that data. - * The value type can be specified by a type parameter "T". - * - * @param – value type - */ - @Data - public static class Sourced { // todo: refactor class to introduce type parameter and make value generic - private T value; - private String source; - } - - /** - * {@link Limited} is a container class that allows storing an actual value along with possible min and max values. - * It is special form of triple. All three values have a generic type that should be a subclass of {@link Number}. - * - * @param – actual, min and max type - */ - @Data - public static class Limited { - // todo: refactor class to introduce type param bounded by number and make fields generic numbers - private final T actual; - private final T min; - private final T max; - } - - /** - * {@link Converter} interface declares a typical contract of a converter. It works with two independent generic types. - * It defines a convert method which accepts one parameter of one type and returns a converted result of another type. - * - * @param – source object type - * @param - converted result type - */ - public interface Converter { // todo: introduce type parameters - // todo: add convert method - R convert(T obj); - } - - /** - * {@link MaxHolder} is a container class that keeps track of the maximum value only. It works with comparable objects - * and allows you to put new values. Every time you put a value, it is stored only if the new value is greater - * than the current max. - * - * @param – value type - */ - public static class MaxHolder> { // todo: refactor class to make it generic - private T max; - - public MaxHolder(T max) { - this.max = max; - } - - /** - * Puts a new value to the holder. A new value is stored to the max, only if it is greater than current max value. - * - * @param val a new value - */ - public void put(T val) { - // throw new ExerciseNotCompletedException(); // todo: update parameter and implement the method - if(val.compareTo(max) > 0){ - max = val; - } - } - - public T getMax() { - return max; - } - } - - /** - * {@link StrictProcessor} defines a contract of a processor that can process only objects that are {@link Serializable} - * and {@link Comparable}. - * - * @param – the type of objects that can be processed - */ - interface StrictProcessor> { // todo: make it generic - void process(T obj); - } - - /** - * {@link CollectionRepository} defines a contract of a runtime store for entities based on any {@link Collection}. - * It has methods that allow to save new entity, and get whole collection. - * - * @param – a type of the entity that should be a subclass of {@link BaseEntity} - * @param – a type of any collection - */ - interface CollectionRepository> { // todo: update interface according to the javadoc - void save(T entity); - C getEntityCollection(); - } - - /** - * {@link ListRepository} extends {@link CollectionRepository} but specifies the underlying collection as - * {@link java.util.List}. - * - * @param – a type of the entity that should be a subclass of {@link BaseEntity} - */ - interface ListRepository extends CollectionRepository> { // todo: update interface according to the javadoc - } - - /** - * {@link ComparableCollection} is a {@link Collection} that can be compared by size. It extends a {@link Collection} - * interface and {@link Comparable} interface, and provides a default implementation of a compareTo method that - * compares collections sizes. - *

- * Please note that size does not depend on the elements type, so it is allowed to compare collections of different - * element types. - * - * @param a type of collection elements - */ - interface ComparableCollection extends Collection, Comparable> { // todo: refactor it to make generic and provide a default impl of compareTo - @Override - default int compareTo(Collection o){ - return Integer.compare(this.size(), o.size()) - } - } - - /** - * {@link CollectionUtil} is an util class that provides various generic helper methods. - */ - static class CollectionUtil { - static final Comparator CREATED_ON_COMPARATOR = Comparator.comparing(BaseEntity::getCreatedOn); - - /** - * An util method that allows to print a dashed list of elements - * - * @param list - */ - public static void print(List list) { - // todo: refactor it so the list of any type can be printed, not only integers - list.forEach(element -> System.out.println(" – " + element)); - } - - /** - * Util method that check if provided collection has new entities. An entity is any object - * that extends {@link BaseEntity}. A new entity is an entity that does not have an id assigned. - * (In other word, which id value equals null). - * - * @param entities provided collection of entities - * @return true if at least one of the elements has null id - */ - public static boolean hasNewEntities(Collection entities) { - //throw new ExerciseNotCompletedException(); // todo: refactor parameter and implement method - return entities.stream() - .anyMatch(e -> e.getUuid() == null); - } - - /** - * Util method that checks if a provided collection of entities is valid. An entity is any subclass of - * a {@link BaseEntity} A validation criteria can be different for different cases, so it is passed - * as second parameter. - * - * @param entities provided collection of entities - * @param validationPredicate criteria for validation - * @return true if all entities fit validation criteria - */ - public static boolean isValidCollection(Collection entities, Predicate validationPredicate) { - //throw new ExerciseNotCompletedException(); // todo: add method parameters and implement the logic - return entities.stream() - .allMatch(validationPredicate); - } - - /** - * hasDuplicates is a generic util method checks if a list of entities contains target entity more than once. - * In other words, it checks if target entity has duplicates in the provided list. A duplicate is an entity that - * has the same UUID. - * - * @param entities given list of entities - * @param targetEntity a target entity - * @param entity type - * @return true if entities list contains target entity more than once - */ - public static boolean hasDuplicates(Collection entities, T targetEntity) { - //throw new ExerciseNotCompletedException(); // todo: update method signature and implement it - return entities.stream() - .filter(e -> e.getUuid().equals(targetEntity.getUuid())) - .count() > 1; - } - - /** - * findMax is a generic util method that accepts an {@link Iterable} and {@link Comparator} and returns an - * optional object, that has maximum "value" based on the given comparator. - * - * @param elements provided iterable of elements - * @param comparator an object that will be used to compare elements - * @param type of elements - * @return optional max value - */ - // todo: create a method and implement its logic manually without using util method from JDK - public static Optional findMax(Iterable elements, Comparator comparator){ - var iterator = elements.iterator(); - if(!iterator.hasNext()){ - return Optional.empty(); - } - var max = iterator.next(); - while(iterator.hasNext()){ - var element = iterator.next(); - if(comparator.compare(element, max) > 0){ - max = element; - } - } - return Optional.of(max); - } - - /** - * findMostRecentlyCreatedEntity is a generic util method that accepts a collection of entities and returns the - * one that is the most recently created. If collection is empty, - * it throws {@link java.util.NoSuchElementException}. - *

- * This method reuses findMax method and passes entities along with prepare comparator instance, - * that is stored as constant CREATED_ON_COMPARATOR. - * - * @param entities provided collection of entities - * @param entity type - * @return an entity from the given collection that has the max createdOn value - */ - // todo: create a method according to JavaDoc and implement it using previous method - public static T findMostRecentlyCreatedEntity(Collection entities){ - return findMax(entities, CREATED_ON_COMPARATOR) - .orElseThrow(); - } - - /** - * An util method that allows to swap two elements of any list. It changes the list so the element with the index - * i will be located on index j, and the element with index j, will be located on the index i. - * Please note that in order to make it convenient and simple, it DOES NOT declare any type parameter. - * - * @param elements a list of any given type - * @param i index of the element to swap - * @param j index of the other element to swap - */ - public static void swap(List elements, int i, int j) { - Objects.checkIndex(i, elements.size()); - Objects.checkIndex(j, elements.size()); - //throw new ExerciseNotCompletedException(); // todo: complete method implementation - swapHelper(elements, i, j); - } - - private static void swapHelper(List elements, int i, int j){ - T temp = elements.get(i); - elements.set(i, elements.get(j)); - elements.set(j, temp); - } - - } -} +package com.bobocode.basics; + +import com.bobocode.basics.util.BaseEntity; +import com.bobocode.util.ExerciseNotCompletedException; +import lombok.Data; + +import java.io.Serializable; +import java.util.*; +import java.util.function.Predicate; + +/** + * {@link CrazyGenerics} is an exercise class. It consists of classes, interfaces and methods that should be updated + * using generics. + *

+ * TODO: go step by step from top to bottom. Read the java doc, write code and run CrazyGenericsTest to verify your impl + *

+ * Hint: in some cases you will need to refactor the code, like replace {@link Object} with a generic type. In order + * cases you will need to add new fields, create new classes, or add new methods. Always try to read java doc and update + * the code according to it. + *

+ * TODO: to get the most out of your learning, visit our website + *

+ * + * @author Taras Boychuk + */ +public class CrazyGenerics { + /** + * {@link Sourced} is a container class that allows storing any object along with the source of that data. + * The value type can be specified by a type parameter "T". + * + * @param – value type + */ + @Data + public static class Sourced { // todo: refactor class to introduce type parameter and make value generic + private T value; + private String source; + } + + /** + * {@link Limited} is a container class that allows storing an actual value along with possible min and max values. + * It is special form of triple. All three values have a generic type that should be a subclass of {@link Number}. + * + * @param – actual, min and max type + */ + @Data + public static class Limited { + // todo: refactor class to introduce type param bounded by number and make fields generic numbers + private final T actual; + private final T min; + private final T max; + } + + /** + * {@link Converter} interface declares a typical contract of a converter. It works with two independent generic types. + * It defines a convert method which accepts one parameter of one type and returns a converted result of another type. + * + * @param – source object type + * @param - converted result type + */ + public interface Converter { // todo: introduce type parameters + // todo: add convert method + R convert(T obj); + } + + /** + * {@link MaxHolder} is a container class that keeps track of the maximum value only. It works with comparable objects + * and allows you to put new values. Every time you put a value, it is stored only if the new value is greater + * than the current max. + * + * @param – value type + */ + public static class MaxHolder> { // todo: refactor class to make it generic + private T max; + + public MaxHolder(T max) { + this.max = max; + } + + /** + * Puts a new value to the holder. A new value is stored to the max, only if it is greater than current max value. + * + * @param val a new value + */ + public void put(T val) { + // throw new ExerciseNotCompletedException(); // todo: update parameter and implement the method + if(val.compareTo(max) > 0){ + max = val; + } + } + + public T getMax() { + return max; + } + } + + /** + * {@link StrictProcessor} defines a contract of a processor that can process only objects that are {@link Serializable} + * and {@link Comparable}. + * + * @param – the type of objects that can be processed + */ + interface StrictProcessor> { // todo: make it generic + void process(T obj); + } + + /** + * {@link CollectionRepository} defines a contract of a runtime store for entities based on any {@link Collection}. + * It has methods that allow to save new entity, and get whole collection. + * + * @param – a type of the entity that should be a subclass of {@link BaseEntity} + * @param – a type of any collection + */ + interface CollectionRepository> { // todo: update interface according to the javadoc + void save(T entity); + C getEntityCollection(); + } + + /** + * {@link ListRepository} extends {@link CollectionRepository} but specifies the underlying collection as + * {@link java.util.List}. + * + * @param – a type of the entity that should be a subclass of {@link BaseEntity} + */ + interface ListRepository extends CollectionRepository> { // todo: update interface according to the javadoc + } + + /** + * {@link ComparableCollection} is a {@link Collection} that can be compared by size. It extends a {@link Collection} + * interface and {@link Comparable} interface, and provides a default implementation of a compareTo method that + * compares collections sizes. + *

+ * Please note that size does not depend on the elements type, so it is allowed to compare collections of different + * element types. + * + * @param a type of collection elements + */ + interface ComparableCollection extends Collection, Comparable> { // todo: refactor it to make generic and provide a default impl of compareTo + @Override + default int compareTo(Collection o){ + return Integer.compare(this.size(), o.size()); + } + } + + /** + * {@link CollectionUtil} is an util class that provides various generic helper methods. + */ + static class CollectionUtil { + static final Comparator CREATED_ON_COMPARATOR = Comparator.comparing(BaseEntity::getCreatedOn); + + /** + * An util method that allows to print a dashed list of elements + * + * @param list + */ + public static void print(List list) { + // todo: refactor it so the list of any type can be printed, not only integers + list.forEach(element -> System.out.println(" – " + element)); + } + + /** + * Util method that check if provided collection has new entities. An entity is any object + * that extends {@link BaseEntity}. A new entity is an entity that does not have an id assigned. + * (In other word, which id value equals null). + * + * @param entities provided collection of entities + * @return true if at least one of the elements has null id + */ + public static boolean hasNewEntities(Collection entities) { + //throw new ExerciseNotCompletedException(); // todo: refactor parameter and implement method + return entities.stream() + .anyMatch(e -> e.getUuid() == null); + } + + /** + * Util method that checks if a provided collection of entities is valid. An entity is any subclass of + * a {@link BaseEntity} A validation criteria can be different for different cases, so it is passed + * as second parameter. + * + * @param entities provided collection of entities + * @param validationPredicate criteria for validation + * @return true if all entities fit validation criteria + */ + public static boolean isValidCollection(Collection entities, Predicate validationPredicate) { + //throw new ExerciseNotCompletedException(); // todo: add method parameters and implement the logic + return entities.stream() + .allMatch(validationPredicate); + } + + /** + * hasDuplicates is a generic util method checks if a list of entities contains target entity more than once. + * In other words, it checks if target entity has duplicates in the provided list. A duplicate is an entity that + * has the same UUID. + * + * @param entities given list of entities + * @param targetEntity a target entity + * @param entity type + * @return true if entities list contains target entity more than once + */ + public static boolean hasDuplicates(Collection entities, T targetEntity) { + //throw new ExerciseNotCompletedException(); // todo: update method signature and implement it + return entities.stream() + .filter(e -> e.getUuid().equals(targetEntity.getUuid())) + .count() > 1; + } + + /** + * findMax is a generic util method that accepts an {@link Iterable} and {@link Comparator} and returns an + * optional object, that has maximum "value" based on the given comparator. + * + * @param elements provided iterable of elements + * @param comparator an object that will be used to compare elements + * @param type of elements + * @return optional max value + */ + // todo: create a method and implement its logic manually without using util method from JDK + public static Optional findMax(Iterable elements, Comparator comparator){ + var iterator = elements.iterator(); + if(!iterator.hasNext()){ + return Optional.empty(); + } + var max = iterator.next(); + while(iterator.hasNext()){ + var element = iterator.next(); + if(comparator.compare(element, max) > 0){ + max = element; + } + } + return Optional.of(max); + } + + /** + * findMostRecentlyCreatedEntity is a generic util method that accepts a collection of entities and returns the + * one that is the most recently created. If collection is empty, + * it throws {@link java.util.NoSuchElementException}. + *

+ * This method reuses findMax method and passes entities along with prepare comparator instance, + * that is stored as constant CREATED_ON_COMPARATOR. + * + * @param entities provided collection of entities + * @param entity type + * @return an entity from the given collection that has the max createdOn value + */ + // todo: create a method according to JavaDoc and implement it using previous method + public static T findMostRecentlyCreatedEntity(Collection entities){ + return findMax(entities, CREATED_ON_COMPARATOR) + .orElseThrow(); + } + + /** + * An util method that allows to swap two elements of any list. It changes the list so the element with the index + * i will be located on index j, and the element with index j, will be located on the index i. + * Please note that in order to make it convenient and simple, it DOES NOT declare any type parameter. + * + * @param elements a list of any given type + * @param i index of the element to swap + * @param j index of the other element to swap + */ + public static void swap(List elements, int i, int j) { + Objects.checkIndex(i, elements.size()); + Objects.checkIndex(j, elements.size()); + //throw new ExerciseNotCompletedException(); // todo: complete method implementation + swapHelper(elements, i, j); + } + + private static void swapHelper(List elements, int i, int j){ + T temp = elements.get(i); + elements.set(i, elements.get(j)); + elements.set(j, temp); + } + + } +}