diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithAnnotation.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithAnnotation.java new file mode 100644 index 0000000000..e168ce19c7 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithAnnotation.java @@ -0,0 +1,5 @@ +package com.ossez.annotations; + +@Deprecated +class ClassWithAnnotation { +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithDeprecatedMethod.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithDeprecatedMethod.java new file mode 100644 index 0000000000..d365a3df8b --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithDeprecatedMethod.java @@ -0,0 +1,9 @@ +package com.ossez.annotations; + +class ClassWithDeprecatedMethod { + + @Deprecated + static void deprecatedMethod() { + + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSafeVarargs.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSafeVarargs.java new file mode 100644 index 0000000000..42ead026ad --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSafeVarargs.java @@ -0,0 +1,11 @@ +package com.ossez.annotations; + +class ClassWithSafeVarargs { + + @SafeVarargs + final void iterateOverVarargs(T... args) { + for (T x : args) { + // do stuff with x + } + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarnings.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarnings.java new file mode 100644 index 0000000000..7d75ce5c66 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/ClassWithSuppressWarnings.java @@ -0,0 +1,9 @@ +package com.ossez.annotations; + +class ClassWithSuppressWarnings { + + @SuppressWarnings("deprecation") + void useDeprecatedMethod() { + ClassWithDeprecatedMethod.deprecatedMethod(); // no warning is generated here + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/IntConsumer.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/IntConsumer.java new file mode 100644 index 0000000000..7ce76b1e6c --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/IntConsumer.java @@ -0,0 +1,8 @@ +package com.ossez.annotations; + +@FunctionalInterface +interface IntConsumer { + + void accept(Integer number); + +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/Interval.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/Interval.java new file mode 100644 index 0000000000..823d50926e --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/Interval.java @@ -0,0 +1,8 @@ +package com.ossez.annotations; + +import java.lang.annotation.Repeatable; + +@Repeatable(Intervals.class) +@interface Interval { + int hour() default 1; +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/IntervalUsage.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/IntervalUsage.java new file mode 100644 index 0000000000..85dd4d5dc4 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/IntervalUsage.java @@ -0,0 +1,9 @@ +package com.ossez.annotations; + +public class IntervalUsage { + + @Interval(hour = 17) + @Interval(hour = 13) + void doPeriodicCleanup() { + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/Intervals.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/Intervals.java new file mode 100644 index 0000000000..db6103d50f --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/Intervals.java @@ -0,0 +1,5 @@ +package com.ossez.annotations; + +@interface Intervals { + Interval[] value(); +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyAnnotation.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyAnnotation.java new file mode 100644 index 0000000000..37b07dbcf6 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyAnnotation.java @@ -0,0 +1,11 @@ +package com.ossez.annotations; + +import java.lang.annotation.*; + +@Inherited +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.LOCAL_VARIABLE, ElementType.FIELD}) +@interface MyAnnotation { + +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyAnnotationTarget.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyAnnotationTarget.java new file mode 100644 index 0000000000..94a689651c --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyAnnotationTarget.java @@ -0,0 +1,16 @@ +package com.ossez.annotations; + +class MyAnnotationTarget { + + // this is OK + @MyAnnotation + String someField; + + // @MyAnnotation <- this is invalid usage! + void doSomething() { + + // this also works + @MyAnnotation + String localVariable; + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyOperation.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyOperation.java new file mode 100644 index 0000000000..3276e9dace --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyOperation.java @@ -0,0 +1,6 @@ +package com.ossez.annotations; + +interface MyOperation { + + void perform(); +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyOperationImpl.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyOperationImpl.java new file mode 100644 index 0000000000..7a6c79b0a6 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/annotations/MyOperationImpl.java @@ -0,0 +1,9 @@ +package com.ossez.annotations; + +class MyOperationImpl implements MyOperation { + + @Override + public void perform() { + + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/Init.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/Init.java new file mode 100644 index 0000000000..f1eb75e068 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/Init.java @@ -0,0 +1,13 @@ +package com.ossez.customannotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(METHOD) +public @interface Init { + +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonElement.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonElement.java new file mode 100644 index 0000000000..31f00eaced --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonElement.java @@ -0,0 +1,13 @@ +package com.ossez.customannotations; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target({ FIELD }) +public @interface JsonElement { + public String key() default ""; +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonSerializable.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonSerializable.java new file mode 100644 index 0000000000..513aa1a69e --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonSerializable.java @@ -0,0 +1,13 @@ +package com.ossez.customannotations; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(TYPE) +public @interface JsonSerializable { + +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonSerializationException.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonSerializationException.java new file mode 100644 index 0000000000..d6c564868f --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/JsonSerializationException.java @@ -0,0 +1,10 @@ +package com.ossez.customannotations; + +public class JsonSerializationException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public JsonSerializationException(String message) { + super(message); + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java new file mode 100644 index 0000000000..d99c5dcc1c --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java @@ -0,0 +1,67 @@ +package com.ossez.customannotations; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class ObjectToJsonConverter { + public String convertToJson(Object object) throws JsonSerializationException { + try { + + checkIfSerializable(object); + initializeObject(object); + return getJsonString(object); + + } catch (Exception e) { + throw new JsonSerializationException(e.getMessage()); + } + } + + private void checkIfSerializable(Object object) { + if (Objects.isNull(object)) { + throw new JsonSerializationException("Can't serialize a null object"); + } + + Class clazz = object.getClass(); + if (!clazz.isAnnotationPresent(JsonSerializable.class)) { + throw new JsonSerializationException("The class " + clazz.getSimpleName() + " is not annotated with JsonSerializable"); + } + } + + private void initializeObject(Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Class clazz = object.getClass(); + for (Method method : clazz.getDeclaredMethods()) { + if (method.isAnnotationPresent(Init.class)) { + method.setAccessible(true); + method.invoke(object); + } + } + } + + private String getJsonString(Object object) throws IllegalArgumentException, IllegalAccessException { + Class clazz = object.getClass(); + Map jsonElementsMap = new HashMap<>(); + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + if (field.isAnnotationPresent(JsonElement.class)) { + jsonElementsMap.put(getKey(field), (String) field.get(object)); + } + } + + String jsonString = jsonElementsMap.entrySet() + .stream() + .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"") + .collect(Collectors.joining(",")); + return "{" + jsonString + "}"; + } + + private String getKey(Field field) { + String value = field.getAnnotation(JsonElement.class) + .key(); + return value.isEmpty() ? field.getName() : value; + } +} diff --git a/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/Person.java b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/Person.java new file mode 100644 index 0000000000..c9ca2d19b7 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/java/com/baeldung/customannotations/Person.java @@ -0,0 +1,66 @@ +package com.ossez.customannotations; + +@JsonSerializable +public class Person { + @JsonElement + private String firstName; + @JsonElement + private String lastName; + @JsonElement(key = "personAge") + private String age; + + private String address; + + public Person(String firstName, String lastName) { + super(); + this.firstName = firstName; + this.lastName = lastName; + } + + public Person(String firstName, String lastName, String age) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + } + + @Init + private void initNames() { + this.firstName = this.firstName.substring(0, 1) + .toUpperCase() + this.firstName.substring(1); + this.lastName = this.lastName.substring(0, 1) + .toUpperCase() + this.lastName.substring(1); + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getAge() { + return age; + } + + public void setAge(String age) { + this.age = age; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + +} diff --git a/core-java-modules/core-java-annotations/src/main/resources/logback.xml b/core-java-modules/core-java-annotations/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-annotations/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-annotations/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java b/core-java-modules/core-java-annotations/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java new file mode 100644 index 0000000000..1b5745e37e --- /dev/null +++ b/core-java-modules/core-java-annotations/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java @@ -0,0 +1,26 @@ +package com.ossez.customannotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +public class JsonSerializerUnitTest { + + @Test + public void givenObjectNotSerializedThenExceptionThrown() throws JsonSerializationException { + Object object = new Object(); + ObjectToJsonConverter serializer = new ObjectToJsonConverter(); + assertThrows(JsonSerializationException.class, () -> { + serializer.convertToJson(object); + }); + } + + @Test + public void givenObjectSerializedThenTrueReturned() throws JsonSerializationException { + Person person = new Person("soufiane", "cheouati", "34"); + ObjectToJsonConverter serializer = new ObjectToJsonConverter(); + String jsonString = serializer.convertToJson(person); + assertEquals("{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}", jsonString); + } +}