From d66bb0fd0b5bd6a10457411077038fe0e6e8c969 Mon Sep 17 00:00:00 2001 From: Kateryna0508 Date: Wed, 23 Oct 2024 01:30:11 +0500 Subject: [PATCH 1/3] java-fundamentals-exercises 0-0-intro --- .../main/java/com/bobocode/intro/ExerciseIntroduction.java | 6 ++---- .../java/com/bobocode/intro/ExerciseIntroductionTest.java | 2 +- 2 files changed, 3 insertions(+), 5 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 35d92563..3bb3ce6d 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 @@ -23,8 +23,7 @@ public class ExerciseIntroduction { * @return "The key to efficient learning is practice!" */ public String getWelcomeMessage() { - // todo: implement a method and return a message according to javadoc - throw new ExerciseNotCompletedException(); + return "The key to efficient learning is practice!"; } /** @@ -39,7 +38,6 @@ public String getWelcomeMessage() { * @return encoded message */ public String encodeMessage(String message) { - // todo: switch to branch "completed" in order to see how it should be implemented - throw new ExerciseNotCompletedException(); + return Base64.getEncoder().encodeToString(message.getBytes()); } } diff --git a/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java b/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java index 093909fe..42ef130f 100644 --- a/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java +++ b/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java @@ -48,4 +48,4 @@ void encodeMessageReturnsCorrectPhrase() { assertThat(encodedMessage).isEqualTo("VGhlIGtleSB0byBlZmZpY2llbnQgbGVhcm5pbmcgaXMgcHJhY3RpY2Uh"); } -} +} \ No newline at end of file From 724e05f7f2930ac5e8ec10d53e250d78af8714ef Mon Sep 17 00:00:00 2001 From: Kateryna0508 Date: Wed, 23 Oct 2024 01:37:30 +0500 Subject: [PATCH 2/3] 1.3.0 & 1.3.1 --- .../main/java/com/bobocode/basics/Box.java | 9 +- .../java/com/bobocode/basics/BoxDemoApp.java | 11 +- .../java/com/bobocode/basics/BoxTest.java | 2 +- .../com/bobocode/basics/CrazyGenerics.java | 110 +++++++++++------- .../com/bobocode/basics/util/BaseEntity.java | 2 +- .../bobocode/basics/CrazyGenericsTest.java | 2 +- 6 files changed, 80 insertions(+), 56 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 5a2d860e..0f6a3bcb 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 @@ -8,17 +8,16 @@ * 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; + 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-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java index bc12174e..da2997c7 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java @@ -9,13 +9,12 @@ */ public class BoxDemoApp { public static void main(String[] args) { - Box intBox = new Box(123); - Box intBox2 = new Box(321); - System.out.println((int) intBox.getValue() + (int) intBox2.getValue()); + Box intBox = new Box<>(123); + Box intBox2 = new Box<>(321); + System.out.println((int) intBox.getValue() + intBox2.getValue()); intBox.setValue(222); - intBox.setValue("abc"); // this should not be allowed - // the following code will compile, but will throw runtime exception - System.out.println((int) intBox.getValue() + (int) intBox2.getValue()); +// intBox.setValue("abc"); // this should not be allowed + System.out.println((int) intBox.getValue() + intBox2.getValue()); } } diff --git a/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java b/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java index 76e0f385..4c9b7f39 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java @@ -81,4 +81,4 @@ void setterParameterIsGeneric() { assertThat(parameter.getParameterizedType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); } -} +} \ No newline at end of file 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 751d5899..66961582 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,14 +1,12 @@ package com.bobocode.basics; import com.bobocode.basics.util.BaseEntity; -import com.bobocode.util.ExerciseNotCompletedException; import lombok.Data; +import lombok.val; 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 { + private T value; private String source; } @@ -45,11 +43,10 @@ public static class Sourced { // todo: refactor class to introduce type paramete * @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 Object actual; - private final Object min; - private final Object max; + public static class Limited { + private final T actual; + private final T min; + private final T max; } /** @@ -59,8 +56,8 @@ public static class Limited { * @param – source object type * @param - converted result type */ - public interface Converter { // todo: introduce type parameters - // todo: add convert method + public interface Converter { + R convert(T obj); } /** @@ -70,10 +67,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 +79,13 @@ 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) { + if (val.compareTo(max) > 0) { + max = val; + } } - public Object getMax() { + public T getMax() { return max; } } @@ -97,8 +96,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 +107,10 @@ 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); + interface CollectionRepository> { // todo: update interface according to the javadoc + void save(T entity); - Collection getEntityCollection(); + C getEntityCollection(); } /** @@ -120,7 +119,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,12 +132,14 @@ 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> { + + @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); @@ -147,8 +148,7 @@ static class CollectionUtil { * * @param list */ - public static void print(List list) { - // todo: refactor it so the list of any type can be printed, not only integers + public static void print(List list) { list.forEach(element -> System.out.println(" – " + element)); } @@ -160,8 +160,9 @@ 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) { + return entities.stream() + .anyMatch(e -> e.getUuid() == null); } /** @@ -173,8 +174,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) { + return entities.stream() + .allMatch(validationPredicate); } /** @@ -187,8 +190,10 @@ 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) { + return entities.stream() + .filter(e -> e.getUuid().equals(targetEntity.getUuid())) + .count() > 1; } /** @@ -200,7 +205,20 @@ public static boolean hasDuplicates() { * @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 @@ -214,7 +232,10 @@ public static boolean hasDuplicates() { * @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 @@ -228,8 +249,13 @@ 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 + 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); + } } -} +} \ No newline at end of file diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java index f961ab7a..41287360 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java @@ -18,4 +18,4 @@ public BaseEntity(UUID uuid) { this.uuid = uuid; this.createdOn = LocalDateTime.now(); } -} +} \ No newline at end of file diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java b/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java index d616e908..2e36a770 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java @@ -858,4 +858,4 @@ public TestEntity(LocalDateTime createdOn) { super(UUID.randomUUID(), createdOn); } } -} +} \ No newline at end of file From ad8d087183fa2db3544c8027bec8d6c26595ed09 Mon Sep 17 00:00:00 2001 From: Kateryna0508 Date: Thu, 31 Oct 2024 17:23:49 +0500 Subject: [PATCH 3/3] fix --- .../bobocode/intro/ExerciseIntroduction.java | 3 +- .../intro/ExerciseIntroductionTest.java | 54 +++---- .../main/java/com/bobocode/basics/Box.java | 3 +- .../java/com/bobocode/basics/BoxDemoApp.java | 13 +- .../java/com/bobocode/basics/BoxTest.java | 148 +++++++++--------- .../com/bobocode/basics/CrazyGenerics.java | 110 +++++-------- .../com/bobocode/basics/util/BaseEntity.java | 2 +- .../bobocode/basics/CrazyGenericsTest.java | 2 +- 8 files changed, 157 insertions(+), 178 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 3bb3ce6d..4e6fa2a2 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 @@ -1,6 +1,7 @@ package com.bobocode.intro; 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. @@ -23,7 +24,7 @@ public class ExerciseIntroduction { * @return "The key to efficient learning is practice!" */ public String getWelcomeMessage() { - return "The key to efficient learning is practice!"; + return "The key to efficient learning is practice!"; } /** diff --git a/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java b/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java index 42ef130f..f8a37c24 100644 --- a/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java +++ b/0-0-intro/src/test/java/com/bobocode/intro/ExerciseIntroductionTest.java @@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** - * This is a {@link ExerciseIntroductionTest} that is meant to verify if you properly implement {@link ExerciseIntroduction}. + * This is a {@link ExerciseIntroductionTest} that is meant to verify if you properly implement {@link ExerciseIntroduction}. * It is a simple example that shows how each exercise is organized: todo section + tests. *

* A typical Java test uses JUnit framework to run the test, and may also use some other frameworks for assertions. @@ -22,30 +22,30 @@ */ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class ExerciseIntroductionTest { - private ExerciseIntroduction exerciseIntroduction = new ExerciseIntroduction(); - private String EXPECTED_MESSAGE = "The key to efficient learning is practice!"; - - @Test - @Order(1) - @DisplayName("getWelcomeMessage method returns correct phrase") - void getWelcomeMessage() { - String message = exerciseIntroduction.getWelcomeMessage(); - - assertThat(message).isEqualTo(EXPECTED_MESSAGE); - } - - @Test - @Order(2) - @DisplayName("encodeMessage returns correct encoded message") - @SneakyThrows - void encodeMessageReturnsCorrectPhrase() { - var encodeMessageMethod = Arrays.stream(ExerciseIntroduction.class.getDeclaredMethods()) - .filter(method -> method.getName().equals("encodeMessage")) - .findAny() - .orElseThrow(); - - var encodedMessage = encodeMessageMethod.invoke(new ExerciseIntroduction(), EXPECTED_MESSAGE); - - assertThat(encodedMessage).isEqualTo("VGhlIGtleSB0byBlZmZpY2llbnQgbGVhcm5pbmcgaXMgcHJhY3RpY2Uh"); - } + private ExerciseIntroduction exerciseIntroduction = new ExerciseIntroduction(); + private String EXPECTED_MESSAGE = "The key to efficient learning is practice!"; + + @Test + @Order(1) + @DisplayName("getWelcomeMessage method returns correct phrase") + void getWelcomeMessage() { + String message = exerciseIntroduction.getWelcomeMessage(); + + assertThat(message).isEqualTo(EXPECTED_MESSAGE); + } + + @Test + @Order(2) + @DisplayName("encodeMessage returns correct encoded message") + @SneakyThrows + void encodeMessageReturnsCorrectPhrase() { + var encodeMessageMethod = Arrays.stream(ExerciseIntroduction.class.getDeclaredMethods()) + .filter(method -> method.getName().equals("encodeMessage")) + .findAny() + .orElseThrow(); + + var encodedMessage = encodeMessageMethod.invoke(new ExerciseIntroduction(), EXPECTED_MESSAGE); + + assertThat(encodedMessage).isEqualTo("VGhlIGtleSB0byBlZmZpY2llbnQgbGVhcm5pbmcgaXMgcHJhY3RpY2Uh"); + } } \ No newline at end of file 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 0f6a3bcb..180603a2 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,7 +7,7 @@ *

* todo: refactor this class so it uses generic type "T" and run {@link com.bobocode.basics.BoxTest} to verify it */ -public class Box { +public class Box { private T value; public Box(T value) { @@ -21,3 +21,4 @@ public T getValue() { public void setValue(T value) { this.value = value; } +} diff --git a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java index da2997c7..fcc9b7fc 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/main/java/com/bobocode/basics/BoxDemoApp.java @@ -1,5 +1,7 @@ package com.bobocode.basics; +import com.bobocode.basics.Box; + /** * This demo demonstrates why using Object is not safe. It's not safe because runtime casting can cause runtime * exceptions. We should always fail as soon as possible. So in this code we should not allow setting String @@ -9,12 +11,13 @@ */ public class BoxDemoApp { public static void main(String[] args) { - Box intBox = new Box<>(123); - Box intBox2 = new Box<>(321); - System.out.println((int) intBox.getValue() + intBox2.getValue()); + Box intBox = new Box(123); + Box intBox2 = new Box(321); + System.out.println((int) intBox.getValue() + (int) intBox2.getValue()); intBox.setValue(222); -// intBox.setValue("abc"); // this should not be allowed - System.out.println((int) intBox.getValue() + intBox2.getValue()); + intBox.setValue("abc"); // this should not be allowed + // the following code will compile, but will throw runtime exception + System.out.println((int) intBox.getValue() + (int) intBox2.getValue()); } } diff --git a/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java b/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java index 4c9b7f39..1d033665 100644 --- a/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java +++ b/1-0-java-basics/1-3-0-hello-generics/src/test/java/com/bobocode/basics/BoxTest.java @@ -7,78 +7,78 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class BoxTest { - private final String TYPE_PARAMETER_NAME = "T"; - - @Test - @Order(1) - @DisplayName("Box class has one type parameter") - void boxClassHasOneTypeParameter() { - var typeParameters = Box.class.getTypeParameters(); - - assertThat(typeParameters.length).isEqualTo(1); - } - - @Test - @Order(2) - @DisplayName("Type parameter is called \"T\"") - void typeParameterIsCalledT() { - var typeParameter = Box.class.getTypeParameters()[0]; - - assertThat(typeParameter.getName()).isEqualTo(TYPE_PARAMETER_NAME); - } - - @Test - @Order(3) - @DisplayName("Type parameter \"T\" is not bounded") - void typeParameterIsNotBounded() { - var typeParameter = Box.class.getTypeParameters()[0]; - - assertThat(typeParameter.getBounds()).hasSize(1); - assertThat(typeParameter.getBounds()[0].getTypeName()).isEqualTo(Object.class.getTypeName()); - } - - @Test - @SneakyThrows - @Order(4) - @DisplayName("Field \"value\" is \"T\"") - void valueFieldIsGeneric() { - var valueField = Box.class.getDeclaredField("value"); - var genericType = valueField.getGenericType(); - - assertThat(genericType.getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); - } - - @Test - @SneakyThrows - @Order(5) - @DisplayName("Constructor parameter type is \"T\"") - void constructorParameterIsGeneric() { - var constructor = Box.class.getDeclaredConstructors()[0]; - assert (constructor.getParameters().length == 1); - var parameter = constructor.getParameters()[0]; - - assertThat(parameter.getParameterizedType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); - } - - @Test - @SneakyThrows - @Order(6) - @DisplayName("Getter return type is \"T\"") - void getterReturnTypeIsGeneric() { - var getter = Box.class.getDeclaredMethod("getValue"); - - assertThat(getter.getGenericReturnType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); - } - - @Test - @SneakyThrows - @Order(7) - @DisplayName("Setter parameter type is \"T\"") - void setterParameterIsGeneric() { - var setter = Box.class.getDeclaredMethod("setValue", Object.class); - assert (setter.getParameters().length == 1); - var parameter = setter.getParameters()[0]; - - assertThat(parameter.getParameterizedType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); - } + private final String TYPE_PARAMETER_NAME = "T"; + + @Test + @Order(1) + @DisplayName("Box class has one type parameter") + void boxClassHasOneTypeParameter() { + var typeParameters = Box.class.getTypeParameters(); + + assertThat(typeParameters.length).isEqualTo(1); + } + + @Test + @Order(2) + @DisplayName("Type parameter is called \"T\"") + void typeParameterIsCalledT() { + var typeParameter = Box.class.getTypeParameters()[0]; + + assertThat(typeParameter.getName()).isEqualTo(TYPE_PARAMETER_NAME); + } + + @Test + @Order(3) + @DisplayName("Type parameter \"T\" is not bounded") + void typeParameterIsNotBounded() { + var typeParameter = Box.class.getTypeParameters()[0]; + + assertThat(typeParameter.getBounds()).hasSize(1); + assertThat(typeParameter.getBounds()[0].getTypeName()).isEqualTo(Object.class.getTypeName()); + } + + @Test + @SneakyThrows + @Order(4) + @DisplayName("Field \"value\" is \"T\"") + void valueFieldIsGeneric() { + var valueField = Box.class.getDeclaredField("value"); + var genericType = valueField.getGenericType(); + + assertThat(genericType.getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); + } + + @Test + @SneakyThrows + @Order(5) + @DisplayName("Constructor parameter type is \"T\"") + void constructorParameterIsGeneric() { + var constructor = Box.class.getDeclaredConstructors()[0]; + assert (constructor.getParameters().length == 1); + var parameter = constructor.getParameters()[0]; + + assertThat(parameter.getParameterizedType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); + } + + @Test + @SneakyThrows + @Order(6) + @DisplayName("Getter return type is \"T\"") + void getterReturnTypeIsGeneric() { + var getter = Box.class.getDeclaredMethod("getValue"); + + assertThat(getter.getGenericReturnType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); + } + + @Test + @SneakyThrows + @Order(7) + @DisplayName("Setter parameter type is \"T\"") + void setterParameterIsGeneric() { + var setter = Box.class.getDeclaredMethod("setValue", Object.class); + assert (setter.getParameters().length == 1); + var parameter = setter.getParameters()[0]; + + assertThat(parameter.getParameterizedType().getTypeName()).isEqualTo(TYPE_PARAMETER_NAME); + } } \ No newline at end of file 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 66961582..751d5899 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,12 +1,14 @@ package com.bobocode.basics; import com.bobocode.basics.util.BaseEntity; +import com.bobocode.util.ExerciseNotCompletedException; import lombok.Data; -import lombok.val; import java.io.Serializable; -import java.util.*; -import java.util.function.Predicate; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; /** * {@link CrazyGenerics} is an exercise class. It consists of classes, interfaces and methods that should be updated @@ -31,8 +33,8 @@ public class CrazyGenerics { * @param – value type */ @Data - public static class Sourced { - private T value; + public static class Sourced { // todo: refactor class to introduce type parameter and make value generic + private Object value; private String source; } @@ -43,10 +45,11 @@ public static class Sourced { * @param – actual, min and max type */ @Data - public static class Limited { - private final T actual; - private final T min; - private final T max; + 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; } /** @@ -56,8 +59,8 @@ public static class Limited { * @param – source object type * @param - converted result type */ - public interface Converter { - R convert(T obj); + public interface Converter { // todo: introduce type parameters + // todo: add convert method } /** @@ -67,10 +70,10 @@ public interface Converter { * * @param – value type */ - public static class MaxHolder> { // todo: refactor class to make it generic - private T max; + public static class MaxHolder { // todo: refactor class to make it generic + private Object max; - public MaxHolder(T max) { + public MaxHolder(Object max) { this.max = max; } @@ -79,13 +82,11 @@ public MaxHolder(T max) { * * @param val a new value */ - public void put(T val) { - if (val.compareTo(max) > 0) { - max = val; - } + public void put(Object val) { + throw new ExerciseNotCompletedException(); // todo: update parameter and implement the method } - public T getMax() { + public Object getMax() { return max; } } @@ -96,8 +97,8 @@ public T getMax() { * * @param – the type of objects that can be processed */ - interface StrictProcessor> { // todo: make it generic - void process(T obj); + interface StrictProcessor { // todo: make it generic + void process(Object obj); } /** @@ -107,10 +108,10 @@ interface StrictProcessor> { // t * @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); + interface CollectionRepository { // todo: update interface according to the javadoc + void save(Object entity); - C getEntityCollection(); + Collection getEntityCollection(); } /** @@ -119,7 +120,7 @@ interface CollectionRepository> { * * @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 + interface ListRepository { // todo: update interface according to the javadoc } /** @@ -132,14 +133,12 @@ interface ListRepository extends CollectionRepository a type of collection elements */ - interface ComparableCollection extends Collection, Comparable> { - - @Override - default int compareTo(Collection o) { - return Integer.compare(this.size(), o.size()); - } + interface ComparableCollection { // todo: refactor it to make generic and provide a default impl of compareTo } + /** + * {@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); @@ -148,7 +147,8 @@ 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,9 +160,8 @@ 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) { - return entities.stream() - .anyMatch(e -> e.getUuid() == null); + public static boolean hasNewEntities(Collection entities) { + throw new ExerciseNotCompletedException(); // todo: refactor parameter and implement method } /** @@ -174,10 +173,8 @@ public static boolean hasNewEntities(Collection entities) * @param validationPredicate criteria for validation * @return true if all entities fit validation criteria */ - public static boolean isValidCollection(Collection entities, - Predicate validationPredicate) { - return entities.stream() - .allMatch(validationPredicate); + public static boolean isValidCollection() { + throw new ExerciseNotCompletedException(); // todo: add method parameters and implement the logic } /** @@ -190,10 +187,8 @@ public static boolean isValidCollection(Collection entitie * @param entity type * @return true if entities list contains target entity more than once */ - public static boolean hasDuplicates(Collection entities, T targetEntity) { - return entities.stream() - .filter(e -> e.getUuid().equals(targetEntity.getUuid())) - .count() > 1; + public static boolean hasDuplicates() { + throw new ExerciseNotCompletedException(); // todo: update method signature and implement it } /** @@ -205,20 +200,7 @@ public static boolean hasDuplicates(Collection entitie * @param type of elements * @return optional max value */ - 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); - } + // todo: create a method and implement its logic manually without using util method from JDK /** * findMostRecentlyCreatedEntity is a generic util method that accepts a collection of entities and returns the @@ -232,10 +214,7 @@ public static Optional findMax(Iterable elements, Comparator entity type * @return an entity from the given collection that has the max createdOn value */ - public static T findMostRecentlyCreatedEntity(Collection entities) { - return findMax(entities, CREATED_ON_COMPARATOR) - .orElseThrow(); - } + // todo: create a method according to JavaDoc and implement it using previous method /** * An util method that allows to swap two elements of any list. It changes the list so the element with the index @@ -249,13 +228,8 @@ public static T findMostRecentlyCreatedEntity(Collection< public static void swap(List elements, int i, int j) { Objects.checkIndex(i, elements.size()); Objects.checkIndex(j, elements.size()); - swapHelper(elements, i, j); + throw new ExerciseNotCompletedException(); // todo: complete method implementation } - 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); - } } -} \ No newline at end of file +} diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java index 41287360..f961ab7a 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/main/java/com/bobocode/basics/util/BaseEntity.java @@ -18,4 +18,4 @@ public BaseEntity(UUID uuid) { this.uuid = uuid; this.createdOn = LocalDateTime.now(); } -} \ No newline at end of file +} diff --git a/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java b/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java index 2e36a770..d616e908 100644 --- a/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java +++ b/1-0-java-basics/1-3-1-crazy-generics/src/test/java/com/bobocode/basics/CrazyGenericsTest.java @@ -858,4 +858,4 @@ public TestEntity(LocalDateTime createdOn) { super(UUID.randomUUID(), createdOn); } } -} \ No newline at end of file +}