diff --git a/checker-plugin/pom.xml b/checker-plugin/pom.xml
new file mode 100644
index 0000000000..bc7a669d4f
--- /dev/null
+++ b/checker-plugin/pom.xml
@@ -0,0 +1,114 @@
+
+ 4.0.0
+ com.baeldung
+ checker-plugin
+ jar
+ 1.0-SNAPSHOT
+ checker-plugin
+ http://maven.apache.org
+
+
+
+
+
+ ${org.checkerframework:jdk8:jar}
+
+
+
+
+
+
+
+
+
+ org.checkerframework
+ checker-qual
+ 2.3.1
+
+
+ org.checkerframework
+ checker
+ 2.3.1
+
+
+ org.checkerframework
+ jdk8
+ 2.3.1
+
+
+
+ org.checkerframework
+ compiler
+ 2.3.1
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+
+
+ properties
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.6.1
+
+
+ 1.8
+
+
+
+ 10000
+ 10000
+
+
+
+ org.checkerframework.checker.nullness.NullnessChecker
+ org.checkerframework.checker.interning.InterningChecker
+ org.checkerframework.checker.fenum.FenumChecker
+ org.checkerframework.checker.formatter.FormatterChecker
+ org.checkerframework.checker.regex.RegexChecker
+
+
+ -AprintErrorStack
+
+
+ -Xbootclasspath/p:${annotatedJdk}
+
+
+
+
+
+ -Awarns
+
+
+
+
+
+
+
diff --git a/checker-plugin/src/main/java/com/baeldung/typechecker/FakeNumExample.java b/checker-plugin/src/main/java/com/baeldung/typechecker/FakeNumExample.java
new file mode 100644
index 0000000000..f1769cfdea
--- /dev/null
+++ b/checker-plugin/src/main/java/com/baeldung/typechecker/FakeNumExample.java
@@ -0,0 +1,42 @@
+package com.baeldung.typechecker;
+
+import org.checkerframework.checker.fenum.qual.Fenum;
+
+//@SuppressWarnings("fenum:assignment.type.incompatible")
+public class FakeNumExample {
+
+ // Here we use some String constants to represents countries.
+ static final @Fenum("country") String ITALY = "IT";
+ static final @Fenum("country") String US = "US";
+ static final @Fenum("country") String UNITED_KINGDOM = "UK";
+
+ // Here we use other String constants to represent planets instead.
+ static final @Fenum("planet") String MARS = "Mars";
+ static final @Fenum("planet") String EARTH = "Earth";
+ static final @Fenum("planet") String VENUS = "Venus";
+
+ // Now we write this method and we want to be sure that
+ // the String parameter has a value of a country, not that is just a String.
+ void greetCountries(@Fenum("country") String country) {
+ System.out.println("Hello " + country);
+ }
+
+ // Similarly we're enforcing here that the provided
+ // parameter is a String that represent a planet.
+ void greetPlanets(@Fenum("planet") String planet) {
+ System.out.println("Hello " + planet);
+ }
+
+ public static void main(String[] args) {
+
+ FakeNumExample obj = new FakeNumExample();
+
+ // This will fail because we pass a planet-String to a method that
+ // accept a country-String.
+ obj.greetCountries(MARS);
+
+ // Here the opposite happens.
+ obj.greetPlanets(US);
+ }
+
+}
diff --git a/checker-plugin/src/main/java/com/baeldung/typechecker/FormatExample.java b/checker-plugin/src/main/java/com/baeldung/typechecker/FormatExample.java
new file mode 100644
index 0000000000..2fa53ff2c2
--- /dev/null
+++ b/checker-plugin/src/main/java/com/baeldung/typechecker/FormatExample.java
@@ -0,0 +1,23 @@
+package com.baeldung.typechecker;
+
+public class FormatExample {
+
+ public static void main(String[] args) {
+
+ // Just enabling org.checkerframework.checker.formatter.FormatterChecker
+ // we can be sure at compile time that the format strings we pass to format()
+ // are correct. Normally we would have those errors raised just at runtime.
+ // All those formats are in fact wrong.
+
+ String.format("%y", 7); // error: invalid format string
+
+ String.format("%d", "a string"); // error: invalid argument type for %d
+
+ String.format("%d %s", 7); // error: missing argument for %s
+
+ String.format("%d", 7, 3); // warning: unused argument 3
+
+ String.format("{0}", 7); // warning: unused argument 7, because {0} is wrong syntax
+ }
+
+}
diff --git a/checker-plugin/src/main/java/com/baeldung/typechecker/KeyForExample.java b/checker-plugin/src/main/java/com/baeldung/typechecker/KeyForExample.java
new file mode 100644
index 0000000000..b3072b72ee
--- /dev/null
+++ b/checker-plugin/src/main/java/com/baeldung/typechecker/KeyForExample.java
@@ -0,0 +1,31 @@
+package com.baeldung.typechecker;
+
+import org.checkerframework.checker.nullness.qual.KeyFor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class KeyForExample {
+
+ private final Map config = new HashMap<>();
+
+ KeyForExample() {
+
+ // Here we initialize a map to store
+ // some config data.
+ config.put("url", "http://1.2.3.4");
+ config.put("name", "foobaz");
+ }
+
+ public void dumpPort() {
+
+ // Here, we want to dump the port value stored in the
+ // config, so we declare that this key has to be
+ // present in the config map.
+ // Obviously that will fail because such key is not present
+ // in the map.
+ @KeyFor("config") String key = "port";
+ System.out.println( config.get(key) );
+ }
+
+}
diff --git a/checker-plugin/src/main/java/com/baeldung/typechecker/MonotonicNotNullExample.java b/checker-plugin/src/main/java/com/baeldung/typechecker/MonotonicNotNullExample.java
new file mode 100644
index 0000000000..c4b9c6afe1
--- /dev/null
+++ b/checker-plugin/src/main/java/com/baeldung/typechecker/MonotonicNotNullExample.java
@@ -0,0 +1,28 @@
+package com.baeldung.typechecker;
+
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
+
+import java.util.Date;
+
+public class MonotonicNotNullExample {
+
+ // The idea is we need this field to be to lazily initialized,
+ // so it starts as null but once it becomes not null
+ // it cannot return null.
+ // In these cases, we can use @MonotonicNonNull
+ @MonotonicNonNull private Date firstCall;
+
+ public Date getFirstCall() {
+ if (firstCall == null) {
+ firstCall = new Date();
+ }
+ return firstCall;
+ }
+
+ public void reset() {
+ // This is reported as error because
+ // we wrongly set the field back to null.
+ firstCall = null;
+ }
+
+}
diff --git a/checker-plugin/src/main/java/com/baeldung/typechecker/NonNullExample.java b/checker-plugin/src/main/java/com/baeldung/typechecker/NonNullExample.java
new file mode 100644
index 0000000000..c929eea23f
--- /dev/null
+++ b/checker-plugin/src/main/java/com/baeldung/typechecker/NonNullExample.java
@@ -0,0 +1,27 @@
+package com.baeldung.typechecker;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public class NonNullExample {
+
+ // This method's parameter is annotated in order
+ // to tell the pluggable type system that it can never be null.
+ private static int countArgs(@NonNull String[] args) {
+ return args.length;
+ }
+
+ // This method's parameter is annotated in order
+ // to tell the pluggable type system that it may be null.
+ public static void main(@Nullable String[] args) {
+
+ // Here lies a potential error,
+ // because we pass a potential null reference to a method
+ // that does not accept nulls.
+ // The Checker Framework will spot this problem at compile time
+ // instead of runtime.
+ System.out.println(countArgs(args));
+
+ }
+
+}
diff --git a/checker-plugin/src/main/java/com/baeldung/typechecker/RegexExample.java b/checker-plugin/src/main/java/com/baeldung/typechecker/RegexExample.java
new file mode 100644
index 0000000000..9503865214
--- /dev/null
+++ b/checker-plugin/src/main/java/com/baeldung/typechecker/RegexExample.java
@@ -0,0 +1,18 @@
+package com.baeldung.typechecker;
+
+import org.checkerframework.checker.regex.qual.Regex;
+
+public class RegexExample {
+
+ // For some reason we want to be sure that this regex
+ // contains at least one capturing group.
+ // However, we do an error and we forgot to define such
+ // capturing group in it.
+ @Regex(1) private static String findNumbers = "\\d*";
+
+ public static void main(String[] args) {
+ String message = "My phone number is +3911223344.";
+ message.matches(findNumbers);
+ }
+
+}
diff --git a/core-groovy/README.md b/core-groovy/README.md
new file mode 100644
index 0000000000..5954a8ab7e
--- /dev/null
+++ b/core-groovy/README.md
@@ -0,0 +1,4 @@
+# Groovy
+
+## Relevant articles:
+
diff --git a/core-groovy/pom.xml b/core-groovy/pom.xml
new file mode 100644
index 0000000000..965670e78e
--- /dev/null
+++ b/core-groovy/pom.xml
@@ -0,0 +1,118 @@
+
+
+ 4.0.0
+
+ core-groovy
+ 1.0-SNAPSHOT
+ jar
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ central
+ http://jcenter.bintray.com
+
+
+
+
+
+ org.codehaus.groovy
+ groovy
+ 2.4.13
+
+
+ org.codehaus.groovy
+ groovy-sql
+ 2.4.13
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.jupiter.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+ org.hsqldb
+ hsqldb
+ 2.4.0
+ test
+
+
+
+
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+ 1.6
+
+
+
+ addSources
+ addTestSources
+ compile
+ compileTests
+
+
+
+
+
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ maven-failsafe-plugin
+ 2.19.1
+
+
+ org.junit.platform
+ junit-platform-surefire-provider
+ ${junit.platform.version}
+
+
+
+
+ junit5
+
+ integration-test
+ verify
+
+
+
+ **/*Test5.java
+
+
+
+
+
+
+
+
+
+ UTF-8
+ 1.1.2
+ 1.1.2
+ 1.1.2
+ 1.1.2
+ 0.15
+ 1.5.0
+
+ 5.0.0
+ 1.0.0
+ 4.12.0
+ 4.12
+
+
+
diff --git a/core-groovy/src/test/groovy/com/baeldung/groovy/sql/SqlTest.groovy b/core-groovy/src/test/groovy/com/baeldung/groovy/sql/SqlTest.groovy
new file mode 100644
index 0000000000..ac96a55773
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/groovy/sql/SqlTest.groovy
@@ -0,0 +1,229 @@
+package com.baeldung.groovy.sql
+
+import groovy.sql.GroovyResultSet
+import groovy.sql.GroovyRowResult
+import groovy.sql.Sql
+import groovy.transform.CompileStatic
+import static org.junit.Assert.*
+import org.junit.Test
+
+class SqlTest {
+
+ final Map dbConnParams = [url: 'jdbc:hsqldb:mem:testDB', user: 'sa', password: '', driver: 'org.hsqldb.jdbc.JDBCDriver']
+
+ @Test
+ void whenNewSqlInstance_thenDbIsAccessed() {
+ def sql = Sql.newInstance(dbConnParams)
+ sql.close()
+ sql.close()
+ }
+
+ @Test
+ void whenTableDoesNotExist_thenSelectFails() {
+ try {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.eachRow('select * from PROJECT') {}
+ }
+
+ fail("An exception should have been thrown")
+ } catch (ignored) {
+ //Ok
+ }
+ }
+
+ @Test
+ void whenTableCreated_thenSelectIsPossible() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ def result = sql.execute 'create table PROJECT_1 (id integer not null, name varchar(50), url varchar(100))'
+
+ assertEquals(0, sql.updateCount)
+ assertFalse(result)
+
+ result = sql.execute('select * from PROJECT_1')
+
+ assertTrue(result)
+ }
+ }
+
+ @Test
+ void whenIdentityColumn_thenInsertReturnsNewId() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.execute 'create table PROJECT_2 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ def ids = sql.executeInsert("INSERT INTO PROJECT_2 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
+
+ assertEquals(0, ids[0][0])
+
+ ids = sql.executeInsert("INSERT INTO PROJECT_2 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
+
+ assertEquals(1, ids[0][0])
+ }
+ }
+
+ @Test
+ void whenUpdate_thenNumberOfAffectedRows() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.execute 'create table PROJECT_3 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
+ sql.executeInsert("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
+ def count = sql.executeUpdate("UPDATE PROJECT_3 SET URL = 'https://' + URL")
+
+ assertEquals(2, count)
+ }
+ }
+
+ @Test
+ void whenEachRow_thenResultSetHasProperties() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.execute 'create table PROJECT_4 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
+ sql.executeInsert("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
+
+ sql.eachRow("SELECT * FROM PROJECT_4") { GroovyResultSet rs ->
+ assertNotNull(rs.name)
+ assertNotNull(rs.url)
+ assertNotNull(rs[0])
+ assertNotNull(rs[1])
+ assertNotNull(rs[2])
+ assertEquals(rs.name, rs['name'])
+ assertEquals(rs.url, rs['url'])
+ }
+ }
+ }
+
+ @Test
+ void whenPagination_thenSubsetIsReturned() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.execute 'create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
+ sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
+ def rows = sql.rows('SELECT * FROM PROJECT_5 ORDER BY NAME', 1, 1)
+
+ assertEquals(1, rows.size())
+ assertEquals('REST with Spring', rows[0].name)
+ }
+ }
+
+ @Test
+ void whenParameters_thenReplacement() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.execute 'create table PROJECT_6 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute('INSERT INTO PROJECT_6 (NAME, URL) VALUES (?, ?)', 'tutorials', 'github.com/eugenp/tutorials')
+ sql.execute("INSERT INTO PROJECT_6 (NAME, URL) VALUES (:name, :url)", [name: 'REST with Spring', url: 'github.com/eugenp/REST-With-Spring'])
+
+ def rows = sql.rows("SELECT * FROM PROJECT_6 WHERE NAME = 'tutorials'")
+
+ assertEquals(1, rows.size())
+
+ rows = sql.rows("SELECT * FROM PROJECT_6 WHERE NAME = 'REST with Spring'")
+
+ assertEquals(1, rows.size())
+ }
+ }
+
+ @Test
+ void whenParametersInGString_thenReplacement() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.execute 'create table PROJECT_7 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.execute "INSERT INTO PROJECT_7 (NAME, URL) VALUES (${'tutorials'}, ${'github.com/eugenp/tutorials'})"
+ def name = 'REST with Spring'
+ def url = 'github.com/eugenp/REST-With-Spring'
+ sql.execute "INSERT INTO PROJECT_7 (NAME, URL) VALUES (${name}, ${url})"
+
+ def rows = sql.rows("SELECT * FROM PROJECT_7 WHERE NAME = 'tutorials'")
+
+ assertEquals(1, rows.size())
+
+ rows = sql.rows("SELECT * FROM PROJECT_7 WHERE NAME = 'REST with Spring'")
+
+ assertEquals(1, rows.size())
+ }
+ }
+
+ @Test
+ void whenTransactionRollback_thenNoDataInserted() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.withTransaction {
+ sql.execute 'create table PROJECT_8 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_8 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
+ sql.executeInsert("INSERT INTO PROJECT_8 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
+ sql.rollback()
+
+ def rows = sql.rows("SELECT * FROM PROJECT_8")
+
+ assertEquals(0, rows.size())
+ }
+ }
+ }
+
+ @Test
+ void whenTransactionRollbackThenCommit_thenOnlyLastInserted() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.withTransaction {
+ sql.execute 'create table PROJECT_9 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
+ sql.rollback()
+ sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
+ sql.rollback()
+ sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
+ sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
+ }
+
+ def rows = sql.rows("SELECT * FROM PROJECT_9")
+
+ assertEquals(2, rows.size())
+ }
+ }
+
+ @Test
+ void whenException_thenTransactionIsRolledBack() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ try {
+ sql.withTransaction {
+ sql.execute 'create table PROJECT_10 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_10 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
+ throw new Exception('rollback')
+ }
+ } catch (ignored) {}
+
+ def rows = sql.rows("SELECT * FROM PROJECT_10")
+
+ assertEquals(0, rows.size())
+ }
+ }
+
+ @Test
+ void givenCachedConnection_whenException_thenDataIsPersisted() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ try {
+ sql.cacheConnection {
+ sql.execute 'create table PROJECT_11 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_11 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
+ throw new Exception('This does not rollback')
+ }
+ } catch (ignored) {}
+
+ def rows = sql.rows("SELECT * FROM PROJECT_11")
+
+ assertEquals(1, rows.size())
+ }
+ }
+
+ /*@Test
+ void whenModifyResultSet_thenDataIsChanged() {
+ Sql.withInstance(dbConnParams) { Sql sql ->
+ sql.execute 'create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
+ sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
+ sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
+
+ sql.eachRow("SELECT * FROM PROJECT_5 FOR UPDATE ") { GroovyResultSet rs ->
+ rs['name'] = "The great ${rs.name}!" as String
+ rs.updateRow()
+ }
+
+ sql.eachRow("SELECT * FROM PROJECT_5") { GroovyResultSet rs ->
+ assertTrue(rs.name.startsWith('The great '))
+ }
+ }
+ }*/
+
+}
diff --git a/core-java-8/README.md b/core-java-8/README.md
index 9260e3d447..1b5208961d 100644
--- a/core-java-8/README.md
+++ b/core-java-8/README.md
@@ -40,3 +40,4 @@
- [Efficient Word Frequency Calculator in Java](http://www.baeldung.com/java-word-frequency)
- [Primitive Type Streams in Java 8](http://www.baeldung.com/java-8-primitive-streams)
- [Fail-Safe Iterator vs Fail-Fast Iterator](http://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator)
+- [Shuffling Collections In Java](http://www.baeldung.com/java-shuffle-collection)
diff --git a/core-java-8/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java b/core-java-8/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java
index 4823c7178a..d013907c9a 100644
--- a/core-java-8/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java
+++ b/core-java-8/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java
@@ -22,7 +22,7 @@ public class ShufflingCollectionsUnitTest {
}
@Test
- public void whenShufflingMapKeys_thenValuesAreShuffled() {
+ public void whenShufflingMapEntries_thenValuesAreShuffled() {
Map studentsById = new HashMap<>();
studentsById.put(1, "Foo");
studentsById.put(2, "Bar");
@@ -32,12 +32,12 @@ public class ShufflingCollectionsUnitTest {
System.out.println("Students before shuffling:");
System.out.println(studentsById.values());
- List shuffledStudentIds = new ArrayList<>(studentsById.keySet());
- Collections.shuffle(shuffledStudentIds);
+ List> shuffledStudentEntries = new ArrayList<>(studentsById.entrySet());
+ Collections.shuffle(shuffledStudentEntries);
- List shuffledStudents = shuffledStudentIds.stream()
- .map(id -> studentsById.get(id))
- .collect(Collectors.toList());
+ List shuffledStudents = shuffledStudentEntries.stream()
+ .map(Map.Entry::getValue)
+ .collect(Collectors.toList());
System.out.println("Students after shuffling");
System.out.println(shuffledStudents);
diff --git a/core-java/src/main/java/com/baeldung/casting/Animal.java b/core-java/src/main/java/com/baeldung/casting/Animal.java
new file mode 100644
index 0000000000..9f31c1dda3
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/casting/Animal.java
@@ -0,0 +1,13 @@
+package com.baeldung.casting;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Animal {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Animal.class);
+
+ public void eat() {
+ LOGGER.info("animal is eating");
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/casting/AnimalFeeder.java b/core-java/src/main/java/com/baeldung/casting/AnimalFeeder.java
new file mode 100644
index 0000000000..89b972e5c2
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/casting/AnimalFeeder.java
@@ -0,0 +1,23 @@
+package com.baeldung.casting;
+
+import java.util.List;
+
+public class AnimalFeeder {
+
+ public void feed(List animals) {
+ animals.forEach(animal -> {
+ animal.eat();
+ if (animal instanceof Cat) {
+ ((Cat) animal).meow();
+ }
+ });
+ }
+
+ public void uncheckedFeed(List animals) {
+ animals.forEach(animal -> {
+ animal.eat();
+ ((Cat) animal).meow();
+ });
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/casting/Cat.java b/core-java/src/main/java/com/baeldung/casting/Cat.java
new file mode 100644
index 0000000000..aa9a9a881a
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/casting/Cat.java
@@ -0,0 +1,16 @@
+package com.baeldung.casting;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Cat extends Animal implements Mew {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Cat.class);
+
+ public void eat() {
+ LOGGER.info("cat is eating");
+ }
+
+ public void meow() {
+ LOGGER.info("meow");
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/casting/Dog.java b/core-java/src/main/java/com/baeldung/casting/Dog.java
new file mode 100644
index 0000000000..763c6b4785
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/casting/Dog.java
@@ -0,0 +1,12 @@
+package com.baeldung.casting;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Dog extends Animal {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Dog.class);
+
+ public void eat() {
+ LOGGER.info("dog is eating");
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/casting/Mew.java b/core-java/src/main/java/com/baeldung/casting/Mew.java
new file mode 100644
index 0000000000..f3c7324551
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/casting/Mew.java
@@ -0,0 +1,5 @@
+package com.baeldung.casting;
+
+public interface Mew {
+ public void meow();
+}
diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProcessor.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProcessor.java
new file mode 100644
index 0000000000..b86a572393
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProcessor.java
@@ -0,0 +1,13 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+public abstract class AuthenticationProcessor {
+
+ // next element in chain or responsibility
+ public AuthenticationProcessor nextProcessor;
+
+ public AuthenticationProcessor(AuthenticationProcessor nextProcessor) {
+ this.nextProcessor = nextProcessor;
+ }
+
+ public abstract boolean isAuthorized(AuthenticationProvider authProvider);
+}
diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProvider.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProvider.java
new file mode 100644
index 0000000000..552a7ff6d9
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/AuthenticationProvider.java
@@ -0,0 +1,5 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+public interface AuthenticationProvider {
+
+}
diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthAuthenticationProcessor.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthAuthenticationProcessor.java
new file mode 100644
index 0000000000..2e2e51fed2
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthAuthenticationProcessor.java
@@ -0,0 +1,21 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+public class OAuthAuthenticationProcessor extends AuthenticationProcessor {
+
+ public OAuthAuthenticationProcessor(AuthenticationProcessor nextProcessor) {
+ super(nextProcessor);
+ }
+
+ @Override
+ public boolean isAuthorized(AuthenticationProvider authProvider) {
+
+ if (authProvider instanceof OAuthTokenProvider) {
+ return Boolean.TRUE;
+ } else if (nextProcessor != null) {
+ return nextProcessor.isAuthorized(authProvider);
+ } else {
+ return Boolean.FALSE;
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthTokenProvider.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthTokenProvider.java
new file mode 100644
index 0000000000..d4e516053b
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/OAuthTokenProvider.java
@@ -0,0 +1,5 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+public class OAuthTokenProvider implements AuthenticationProvider {
+
+}
diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/SamlAuthenticationProvider.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/SamlAuthenticationProvider.java
new file mode 100644
index 0000000000..533b2b4a2d
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/SamlAuthenticationProvider.java
@@ -0,0 +1,5 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+public class SamlAuthenticationProvider implements AuthenticationProvider {
+
+}
diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java
new file mode 100644
index 0000000000..df600c35db
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordAuthenticationProcessor.java
@@ -0,0 +1,20 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+public class UsernamePasswordAuthenticationProcessor extends AuthenticationProcessor {
+
+ public UsernamePasswordAuthenticationProcessor(AuthenticationProcessor nextProcessor) {
+ super(nextProcessor);
+ }
+
+ @Override
+ public boolean isAuthorized(AuthenticationProvider authProvider) {
+ if (authProvider instanceof UsernamePasswordProvider) {
+ return Boolean.TRUE;
+ } else if (nextProcessor != null) {
+ return nextProcessor.isAuthorized(authProvider);
+ } else {
+ return Boolean.FALSE;
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordProvider.java b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordProvider.java
new file mode 100644
index 0000000000..9fbfa7554d
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/designpatterns/chainofresponsibility/UsernamePasswordProvider.java
@@ -0,0 +1,5 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+public class UsernamePasswordProvider implements AuthenticationProvider {
+
+}
diff --git a/core-java/src/main/java/com/baeldung/java/list/CustomList.java b/core-java/src/main/java/com/baeldung/java/list/CustomList.java
new file mode 100644
index 0000000000..bc1321b1a3
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/list/CustomList.java
@@ -0,0 +1,229 @@
+package com.baeldung.java.list;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+public class CustomList implements List {
+ private Object[] internal = {};
+
+ @Override
+ public void add(int index, E element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection extends E> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(int index, Collection extends E> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public E remove(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return internal.length;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return internal.length == 0;
+ }
+
+ @Override
+ public boolean add(E element) {
+ // the first cycle
+ // internal = new Object[1];
+ // internal[0] = element;
+ // return true;
+
+ Object[] temp = new Object[internal.length + 1];
+ System.arraycopy(internal, 0, temp, 0, internal.length);
+ temp[internal.length] = element;
+ internal = temp;
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E get(int index) {
+ return (E) internal[index];
+ }
+
+ @Override
+ public boolean contains(Object object) {
+ // return false
+
+ for (Object element : internal) {
+ if (object.equals(element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean containsAll(Collection> collection) {
+ // the first cycle
+ // for (Object element : collection) {
+ // if (element.equals(internal[0])) {
+ // return true;
+ // }
+ // }
+ // return false;
+
+ for (Object element : collection)
+ if (!contains(element)) {
+ return false;
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E set(int index, E element) {
+ E oldElement = (E) internal[index];
+ internal[index] = element;
+ return oldElement;
+ }
+
+ @Override
+ public void clear() {
+ internal = new Object[0];
+ }
+
+ @Override
+ public int indexOf(Object object) {
+ // the first cycle
+ // if (object.equals(internal[0])) {
+ // return 0;
+ // }
+ // return -1;
+
+ for (int i = 0; i < internal.length; i++) {
+ if (object.equals(internal[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int lastIndexOf(Object object) {
+ // the first cycle
+ // if (object.equals(internal[0])) {
+ // return 0;
+ // }
+ // return -1;
+
+ for (int i = internal.length - 1; i >= 0; i--) {
+ if (object.equals(internal[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List subList(int fromIndex, int toIndex) {
+ // the first cycle
+ // return (List) Arrays.asList(internal);
+
+ Object[] temp = new Object[toIndex - fromIndex];
+ System.arraycopy(internal, fromIndex, temp, 0, temp.length);
+ return (List) Arrays.asList(temp);
+ }
+
+ @Override
+ public Object[] toArray() {
+ return Arrays.copyOf(internal, internal.length);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T[] toArray(T[] array) {
+ // the first cycle
+ // array[0] = (T) internal[0];
+ // return array;
+
+ // the second cycle
+ // if (array.length < internal.length) {
+ // return (T[]) Arrays.copyOf(internal, internal.length, array.getClass());
+ // }
+ // return (T[]) Arrays.copyOf(internal, internal.length, array.getClass());
+
+ if (array.length < internal.length) {
+ return (T[]) Arrays.copyOf(internal, internal.length, array.getClass());
+ }
+
+ System.arraycopy(internal, 0, array, 0, internal.length);
+ if (array.length > internal.length) {
+ array[internal.length] = null;
+ }
+ return array;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new CustomIterator();
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ return null;
+ }
+
+ @Override
+ public ListIterator listIterator(int index) {
+ // ignored for brevity
+ return null;
+ }
+
+ private class CustomIterator implements Iterator {
+ int index;
+
+ @Override
+ public boolean hasNext() {
+ // the first cycle
+ // return true;
+
+ return index != internal.length;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E next() {
+ // the first cycle
+ // return (E) CustomList.this.internal[0];
+
+ E element = (E) CustomList.this.internal[index];
+ index++;
+ return element;
+ }
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/casting/CastingTest.java b/core-java/src/test/java/com/baeldung/casting/CastingTest.java
new file mode 100644
index 0000000000..0ca1ce88dc
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/casting/CastingTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.casting;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CastingTest {
+
+ @Test
+ public void whenPrimitiveConverted_thenValueChanged() {
+ double myDouble = 1.1;
+ int myInt = (int) myDouble;
+ assertNotEquals(myDouble, myInt);
+ }
+
+ @Test
+ public void whenUpcast_thenInstanceUnchanged() {
+ Cat cat = new Cat();
+ Animal animal = cat;
+ animal = (Animal) cat;
+ assertTrue(animal instanceof Cat);
+ }
+
+ @Test
+ public void whenUpcastToObject_thenInstanceUnchanged() {
+ Object object = new Animal();
+ assertTrue(object instanceof Animal);
+ }
+
+ @Test
+ public void whenUpcastToInterface_thenInstanceUnchanged() {
+ Mew mew = new Cat();
+ assertTrue(mew instanceof Cat);
+ }
+
+ @Test
+ public void whenUpcastToAnimal_thenOverridenMethodsCalled() {
+ List animals = new ArrayList<>();
+ animals.add(new Cat());
+ animals.add(new Dog());
+ new AnimalFeeder().feed(animals);
+ }
+
+ @Test
+ public void whenDowncastToCat_thenMeowIsCalled() {
+ Animal animal = new Cat();
+ ((Cat) animal).meow();
+ }
+
+ @Test(expected = ClassCastException.class)
+ public void whenDownCastWithoutCheck_thenExceptionThrown() {
+ List animals = new ArrayList<>();
+ animals.add(new Cat());
+ animals.add(new Dog());
+ new AnimalFeeder().uncheckedFeed(animals);
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/designpatterns/chainofresponsibility/ChainOfResponsibilityTest.java b/core-java/src/test/java/com/baeldung/designpatterns/chainofresponsibility/ChainOfResponsibilityTest.java
new file mode 100644
index 0000000000..a28577efb1
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/designpatterns/chainofresponsibility/ChainOfResponsibilityTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.designpatterns.chainofresponsibility;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+public class ChainOfResponsibilityTest {
+
+ private static AuthenticationProcessor getChainOfAuthProcessor() {
+
+ AuthenticationProcessor oAuthProcessor = new OAuthAuthenticationProcessor(null);
+ AuthenticationProcessor unamePasswordProcessor = new UsernamePasswordAuthenticationProcessor(oAuthProcessor);
+ return unamePasswordProcessor;
+ }
+
+ @Test
+ public void givenOAuthProvider_whenCheckingAuthorized_thenSuccess() {
+ AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor();
+ boolean isAuthorized = authProcessorChain.isAuthorized(new OAuthTokenProvider());
+ assertTrue(isAuthorized);
+ }
+
+ @Test
+ public void givenUsernamePasswordProvider_whenCheckingAuthorized_thenSuccess() {
+ AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor();
+ boolean isAuthorized = authProcessorChain.isAuthorized(new UsernamePasswordProvider());
+ assertTrue(isAuthorized);
+ }
+
+ @Test
+ public void givenSamlAuthProvider_whenCheckingAuthorized_thenFailure() {
+ AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor();
+ boolean isAuthorized = authProcessorChain.isAuthorized(new SamlAuthenticationProvider());
+ assertTrue(!isAuthorized);
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/java/list/CustomListUnitTest.java b/core-java/src/test/java/com/baeldung/java/list/CustomListUnitTest.java
new file mode 100644
index 0000000000..3ee3195e80
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/java/list/CustomListUnitTest.java
@@ -0,0 +1,282 @@
+package com.baeldung.java.list;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Test;
+
+public class CustomListUnitTest {
+ @Test(expected = UnsupportedOperationException.class)
+ public void whenAddToSpecifiedIndex_thenExceptionIsThrown() {
+ new CustomList<>().add(0, null);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void whenAddAllToTheEnd_thenExceptionIsThrown() {
+ Collection