path = dfs.solve(maze);
+ maze.printPath(path);
+ maze.reset();
+ }
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Constants.java b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Constants.java
new file mode 100644
index 0000000000..b646c686b2
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Constants.java
@@ -0,0 +1,47 @@
+package com.baeldung.algorithms.multiswarm;
+
+/**
+ * Constants used by the Multi-swarm optimization algorithms.
+ *
+ * @author Donato Rimenti
+ *
+ */
+public class Constants {
+
+ /**
+ * The inertia factor encourages a particle to continue moving in its
+ * current direction.
+ */
+ public static final double INERTIA_FACTOR = 0.729;
+
+ /**
+ * The cognitive weight encourages a particle to move toward its historical
+ * best-known position.
+ */
+ public static final double COGNITIVE_WEIGHT = 1.49445;
+
+ /**
+ * The social weight encourages a particle to move toward the best-known
+ * position found by any of the particle’s swarm-mates.
+ */
+ public static final double SOCIAL_WEIGHT = 1.49445;
+
+ /**
+ * The global weight encourages a particle to move toward the best-known
+ * position found by any particle in any swarm.
+ */
+ public static final double GLOBAL_WEIGHT = 0.3645;
+
+ /**
+ * Upper bound for the random generation. We use it to reduce the
+ * computation time since we can rawly estimate it.
+ */
+ public static final int PARTICLE_UPPER_BOUND = 10000000;
+
+ /**
+ * Private constructor for utility class.
+ */
+ private Constants() {
+ }
+
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/FitnessFunction.java b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/FitnessFunction.java
new file mode 100644
index 0000000000..2d86ec8d94
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/FitnessFunction.java
@@ -0,0 +1,21 @@
+package com.baeldung.algorithms.multiswarm;
+
+/**
+ * Interface for a fitness function, used to decouple the main algorithm logic
+ * from the specific problem solution.
+ *
+ * @author Donato Rimenti
+ *
+ */
+public interface FitnessFunction {
+
+ /**
+ * Returns the fitness of a particle given its position.
+ *
+ * @param particlePosition
+ * the position of the particle
+ * @return the fitness of the particle
+ */
+ public double getFitness(long[] particlePosition);
+
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Multiswarm.java b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Multiswarm.java
new file mode 100644
index 0000000000..ef60726278
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Multiswarm.java
@@ -0,0 +1,227 @@
+package com.baeldung.algorithms.multiswarm;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Represents a collection of {@link Swarm}.
+ *
+ * @author Donato Rimenti
+ *
+ */
+public class Multiswarm {
+
+ /**
+ * The swarms managed by this multiswarm.
+ */
+ private Swarm[] swarms;
+
+ /**
+ * The best position found within all the {@link #swarms}.
+ */
+ private long[] bestPosition;
+
+ /**
+ * The best fitness score found within all the {@link #swarms}.
+ */
+ private double bestFitness = Double.NEGATIVE_INFINITY;
+
+ /**
+ * A random generator.
+ */
+ private Random random = new Random();
+
+ /**
+ * The fitness function used to determine how good is a particle.
+ */
+ private FitnessFunction fitnessFunction;
+
+ /**
+ * Instantiates a new Multiswarm.
+ *
+ * @param numSwarms
+ * the number of {@link #swarms}
+ * @param particlesPerSwarm
+ * the number of particle for each {@link #swarms}
+ * @param fitnessFunction
+ * the {@link #fitnessFunction}
+ */
+ public Multiswarm(int numSwarms, int particlesPerSwarm, FitnessFunction fitnessFunction) {
+ this.fitnessFunction = fitnessFunction;
+ this.swarms = new Swarm[numSwarms];
+ for (int i = 0; i < numSwarms; i++) {
+ swarms[i] = new Swarm(particlesPerSwarm);
+ }
+ }
+
+ /**
+ * Main loop of the algorithm. Iterates all particles of all
+ * {@link #swarms}. For each particle, computes the new fitness and checks
+ * if a new best position has been found among itself, the swarm and all the
+ * swarms and finally updates the particle position and speed.
+ */
+ public void mainLoop() {
+ for (Swarm swarm : swarms) {
+ for (Particle particle : swarm.getParticles()) {
+
+ long[] particleOldPosition = particle.getPosition().clone();
+
+ // Calculate the particle fitness.
+ particle.setFitness(fitnessFunction.getFitness(particleOldPosition));
+
+ // Check if a new best position has been found for the particle
+ // itself, within the swarm and the multiswarm.
+ if (particle.getFitness() > particle.getBestFitness()) {
+ particle.setBestFitness(particle.getFitness());
+ particle.setBestPosition(particleOldPosition);
+
+ if (particle.getFitness() > swarm.getBestFitness()) {
+ swarm.setBestFitness(particle.getFitness());
+ swarm.setBestPosition(particleOldPosition);
+
+ if (swarm.getBestFitness() > bestFitness) {
+ bestFitness = swarm.getBestFitness();
+ bestPosition = swarm.getBestPosition().clone();
+ }
+
+ }
+ }
+
+ // Updates the particle position by adding the speed to the
+ // actual position.
+ long[] position = particle.getPosition();
+ long[] speed = particle.getSpeed();
+
+ position[0] += speed[0];
+ position[1] += speed[1];
+
+ // Updates the particle speed.
+ speed[0] = getNewParticleSpeedForIndex(particle, swarm, 0);
+ speed[1] = getNewParticleSpeedForIndex(particle, swarm, 1);
+ }
+ }
+ }
+
+ /**
+ * Computes a new speed for a given particle of a given swarm on a given
+ * axis. The new speed is computed using the formula:
+ *
+ *
+ * ({@link Constants#INERTIA_FACTOR} * {@link Particle#getSpeed()}) +
+ * (({@link Constants#COGNITIVE_WEIGHT} * random(0,1)) * ({@link Particle#getBestPosition()} - {@link Particle#getPosition()})) +
+ * (({@link Constants#SOCIAL_WEIGHT} * random(0,1)) * ({@link Swarm#getBestPosition()} - {@link Particle#getPosition()})) +
+ * (({@link Constants#GLOBAL_WEIGHT} * random(0,1)) * ({@link #bestPosition} - {@link Particle#getPosition()}))
+ *
+ *
+ * @param particle
+ * the particle whose new speed needs to be computed
+ * @param swarm
+ * the swarm which contains the particle
+ * @param index
+ * the index of the particle axis whose speeds needs to be
+ * computed
+ * @return the new speed of the particle passed on the given axis
+ */
+ private int getNewParticleSpeedForIndex(Particle particle, Swarm swarm, int index) {
+ return (int) ((Constants.INERTIA_FACTOR * particle.getSpeed()[index])
+ + (randomizePercentage(Constants.COGNITIVE_WEIGHT)
+ * (particle.getBestPosition()[index] - particle.getPosition()[index]))
+ + (randomizePercentage(Constants.SOCIAL_WEIGHT)
+ * (swarm.getBestPosition()[index] - particle.getPosition()[index]))
+ + (randomizePercentage(Constants.GLOBAL_WEIGHT)
+ * (bestPosition[index] - particle.getPosition()[index])));
+ }
+
+ /**
+ * Returns a random number between 0 and the value passed as argument.
+ *
+ * @param value
+ * the value to randomize
+ * @return a random value between 0 and the one passed as argument
+ */
+ private double randomizePercentage(double value) {
+ return random.nextDouble() * value;
+ }
+
+ /**
+ * Gets the {@link #bestPosition}.
+ *
+ * @return the {@link #bestPosition}
+ */
+ public long[] getBestPosition() {
+ return bestPosition;
+ }
+
+ /**
+ * Gets the {@link #bestFitness}.
+ *
+ * @return the {@link #bestFitness}
+ */
+ public double getBestFitness() {
+ return bestFitness;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ long temp;
+ temp = Double.doubleToLongBits(bestFitness);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ result = prime * result + Arrays.hashCode(bestPosition);
+ result = prime * result + ((fitnessFunction == null) ? 0 : fitnessFunction.hashCode());
+ result = prime * result + ((random == null) ? 0 : random.hashCode());
+ result = prime * result + Arrays.hashCode(swarms);
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Multiswarm other = (Multiswarm) obj;
+ if (Double.doubleToLongBits(bestFitness) != Double.doubleToLongBits(other.bestFitness))
+ return false;
+ if (!Arrays.equals(bestPosition, other.bestPosition))
+ return false;
+ if (fitnessFunction == null) {
+ if (other.fitnessFunction != null)
+ return false;
+ } else if (!fitnessFunction.equals(other.fitnessFunction))
+ return false;
+ if (random == null) {
+ if (other.random != null)
+ return false;
+ } else if (!random.equals(other.random))
+ return false;
+ if (!Arrays.equals(swarms, other.swarms))
+ return false;
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Multiswarm [swarms=" + Arrays.toString(swarms) + ", bestPosition=" + Arrays.toString(bestPosition)
+ + ", bestFitness=" + bestFitness + ", random=" + random + ", fitnessFunction=" + fitnessFunction + "]";
+ }
+
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Particle.java b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Particle.java
new file mode 100644
index 0000000000..5930a94267
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Particle.java
@@ -0,0 +1,204 @@
+package com.baeldung.algorithms.multiswarm;
+
+import java.util.Arrays;
+
+/**
+ * Represents a particle, the basic component of a {@link Swarm}.
+ *
+ * @author Donato Rimenti
+ *
+ */
+public class Particle {
+
+ /**
+ * The current position of this particle.
+ */
+ private long[] position;
+
+ /**
+ * The speed of this particle.
+ */
+ private long[] speed;
+
+ /**
+ * The fitness of this particle for the current position.
+ */
+ private double fitness;
+
+ /**
+ * The best position found by this particle.
+ */
+ private long[] bestPosition;
+
+ /**
+ * The best fitness found by this particle.
+ */
+ private double bestFitness = Double.NEGATIVE_INFINITY;
+
+ /**
+ * Instantiates a new Particle.
+ *
+ * @param initialPosition
+ * the initial {@link #position}
+ * @param initialSpeed
+ * the initial {@link #speed}
+ */
+ public Particle(long[] initialPosition, long[] initialSpeed) {
+ this.position = initialPosition;
+ this.speed = initialSpeed;
+ }
+
+ /**
+ * Gets the {@link #position}.
+ *
+ * @return the {@link #position}
+ */
+ public long[] getPosition() {
+ return position;
+ }
+
+ /**
+ * Gets the {@link #speed}.
+ *
+ * @return the {@link #speed}
+ */
+ public long[] getSpeed() {
+ return speed;
+ }
+
+ /**
+ * Gets the {@link #fitness}.
+ *
+ * @return the {@link #fitness}
+ */
+ public double getFitness() {
+ return fitness;
+ }
+
+ /**
+ * Gets the {@link #bestPosition}.
+ *
+ * @return the {@link #bestPosition}
+ */
+ public long[] getBestPosition() {
+ return bestPosition;
+ }
+
+ /**
+ * Gets the {@link #bestFitness}.
+ *
+ * @return the {@link #bestFitness}
+ */
+ public double getBestFitness() {
+ return bestFitness;
+ }
+
+ /**
+ * Sets the {@link #position}.
+ *
+ * @param position
+ * the new {@link #position}
+ */
+ public void setPosition(long[] position) {
+ this.position = position;
+ }
+
+ /**
+ * Sets the {@link #speed}.
+ *
+ * @param speed
+ * the new {@link #speed}
+ */
+ public void setSpeed(long[] speed) {
+ this.speed = speed;
+ }
+
+ /**
+ * Sets the {@link #fitness}.
+ *
+ * @param fitness
+ * the new {@link #fitness}
+ */
+ public void setFitness(double fitness) {
+ this.fitness = fitness;
+ }
+
+ /**
+ * Sets the {@link #bestPosition}.
+ *
+ * @param bestPosition
+ * the new {@link #bestPosition}
+ */
+ public void setBestPosition(long[] bestPosition) {
+ this.bestPosition = bestPosition;
+ }
+
+ /**
+ * Sets the {@link #bestFitness}.
+ *
+ * @param bestFitness
+ * the new {@link #bestFitness}
+ */
+ public void setBestFitness(double bestFitness) {
+ this.bestFitness = bestFitness;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ long temp;
+ temp = Double.doubleToLongBits(bestFitness);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ result = prime * result + Arrays.hashCode(bestPosition);
+ temp = Double.doubleToLongBits(fitness);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ result = prime * result + Arrays.hashCode(position);
+ result = prime * result + Arrays.hashCode(speed);
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Particle other = (Particle) obj;
+ if (Double.doubleToLongBits(bestFitness) != Double.doubleToLongBits(other.bestFitness))
+ return false;
+ if (!Arrays.equals(bestPosition, other.bestPosition))
+ return false;
+ if (Double.doubleToLongBits(fitness) != Double.doubleToLongBits(other.fitness))
+ return false;
+ if (!Arrays.equals(position, other.position))
+ return false;
+ if (!Arrays.equals(speed, other.speed))
+ return false;
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Particle [position=" + Arrays.toString(position) + ", speed=" + Arrays.toString(speed) + ", fitness="
+ + fitness + ", bestPosition=" + Arrays.toString(bestPosition) + ", bestFitness=" + bestFitness + "]";
+ }
+
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Swarm.java b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Swarm.java
new file mode 100644
index 0000000000..e6d37bb7e6
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/multiswarm/Swarm.java
@@ -0,0 +1,155 @@
+package com.baeldung.algorithms.multiswarm;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Represents a collection of {@link Particle}.
+ *
+ * @author Donato Rimenti
+ *
+ */
+public class Swarm {
+
+ /**
+ * The particles of this swarm.
+ */
+ private Particle[] particles;
+
+ /**
+ * The best position found within the particles of this swarm.
+ */
+ private long[] bestPosition;
+
+ /**
+ * The best fitness score found within the particles of this swarm.
+ */
+ private double bestFitness = Double.NEGATIVE_INFINITY;
+
+ /**
+ * A random generator.
+ */
+ private Random random = new Random();
+
+ /**
+ * Instantiates a new Swarm.
+ *
+ * @param numParticles
+ * the number of particles of the swarm
+ */
+ public Swarm(int numParticles) {
+ particles = new Particle[numParticles];
+ for (int i = 0; i < numParticles; i++) {
+ long[] initialParticlePosition = { random.nextInt(Constants.PARTICLE_UPPER_BOUND),
+ random.nextInt(Constants.PARTICLE_UPPER_BOUND) };
+ long[] initialParticleSpeed = { random.nextInt(Constants.PARTICLE_UPPER_BOUND),
+ random.nextInt(Constants.PARTICLE_UPPER_BOUND) };
+ particles[i] = new Particle(initialParticlePosition, initialParticleSpeed);
+ }
+ }
+
+ /**
+ * Gets the {@link #particles}.
+ *
+ * @return the {@link #particles}
+ */
+ public Particle[] getParticles() {
+ return particles;
+ }
+
+ /**
+ * Gets the {@link #bestPosition}.
+ *
+ * @return the {@link #bestPosition}
+ */
+ public long[] getBestPosition() {
+ return bestPosition;
+ }
+
+ /**
+ * Gets the {@link #bestFitness}.
+ *
+ * @return the {@link #bestFitness}
+ */
+ public double getBestFitness() {
+ return bestFitness;
+ }
+
+ /**
+ * Sets the {@link #bestPosition}.
+ *
+ * @param bestPosition
+ * the new {@link #bestPosition}
+ */
+ public void setBestPosition(long[] bestPosition) {
+ this.bestPosition = bestPosition;
+ }
+
+ /**
+ * Sets the {@link #bestFitness}.
+ *
+ * @param bestFitness
+ * the new {@link #bestFitness}
+ */
+ public void setBestFitness(double bestFitness) {
+ this.bestFitness = bestFitness;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ long temp;
+ temp = Double.doubleToLongBits(bestFitness);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ result = prime * result + Arrays.hashCode(bestPosition);
+ result = prime * result + Arrays.hashCode(particles);
+ result = prime * result + ((random == null) ? 0 : random.hashCode());
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Swarm other = (Swarm) obj;
+ if (Double.doubleToLongBits(bestFitness) != Double.doubleToLongBits(other.bestFitness))
+ return false;
+ if (!Arrays.equals(bestPosition, other.bestPosition))
+ return false;
+ if (!Arrays.equals(particles, other.particles))
+ return false;
+ if (random == null) {
+ if (other.random != null)
+ return false;
+ } else if (!random.equals(other.random))
+ return false;
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Swarm [particles=" + Arrays.toString(particles) + ", bestPosition=" + Arrays.toString(bestPosition)
+ + ", bestFitness=" + bestFitness + ", random=" + random + "]";
+ }
+
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/numberwordconverter/NumberWordConverter.java b/algorithms/src/main/java/com/baeldung/algorithms/numberwordconverter/NumberWordConverter.java
new file mode 100644
index 0000000000..0fe2960f96
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/numberwordconverter/NumberWordConverter.java
@@ -0,0 +1,75 @@
+package com.baeldung.algorithms.numberwordconverter;
+
+import java.math.BigDecimal;
+
+import pl.allegro.finance.tradukisto.MoneyConverters;
+
+public class NumberWordConverter {
+
+ public static final String INVALID_INPUT_GIVEN = "Invalid input given";
+
+ public static final String[] ones = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
+
+ public static final String[] tens = {
+ "", // 0
+ "", // 1
+ "twenty", // 2
+ "thirty", // 3
+ "forty", // 4
+ "fifty", // 5
+ "sixty", // 6
+ "seventy", // 7
+ "eighty", // 8
+ "ninety" // 9
+ };
+
+ public static String getMoneyIntoWords(String input) {
+ MoneyConverters converter = MoneyConverters.ENGLISH_BANKING_MONEY_VALUE;
+ return converter.asWords(new BigDecimal(input));
+ }
+
+ public static String getMoneyIntoWords(final double money) {
+ long dollar = (long) money;
+ long cents = Math.round((money - dollar) * 100);
+ if (money == 0D) {
+ return "";
+ }
+ if (money < 0) {
+ return INVALID_INPUT_GIVEN;
+ }
+ String dollarPart = "";
+ if (dollar > 0) {
+ dollarPart = convert(dollar) + " dollar" + (dollar == 1 ? "" : "s");
+ }
+ String centsPart = "";
+ if (cents > 0) {
+ if (dollarPart.length() > 0) {
+ centsPart = " and ";
+ }
+ centsPart += convert(cents) + " cent" + (cents == 1 ? "" : "s");
+ }
+ return dollarPart + centsPart;
+ }
+
+ private static String convert(final long n) {
+ if (n < 0) {
+ return INVALID_INPUT_GIVEN;
+ }
+ if (n < 20) {
+ return ones[(int) n];
+ }
+ if (n < 100) {
+ return tens[(int) n / 10] + ((n % 10 != 0) ? " " : "") + ones[(int) n % 10];
+ }
+ if (n < 1000) {
+ return ones[(int) n / 100] + " hundred" + ((n % 100 != 0) ? " " : "") + convert(n % 100);
+ }
+ if (n < 1_000_000) {
+ return convert(n / 1000) + " thousand" + ((n % 1000 != 0) ? " " : "") + convert(n % 1000);
+ }
+ if (n < 1_000_000_000) {
+ return convert(n / 1_000_000) + " million" + ((n % 1_000_000 != 0) ? " " : "") + convert(n % 1_000_000);
+ }
+ return convert(n / 1_000_000_000) + " billion" + ((n % 1_000_000_000 != 0) ? " " : "") + convert(n % 1_000_000_000);
+ }
+}
\ No newline at end of file
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/prime/PrimeGenerator.java b/algorithms/src/main/java/com/baeldung/algorithms/prime/PrimeGenerator.java
new file mode 100644
index 0000000000..48d51a8848
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/prime/PrimeGenerator.java
@@ -0,0 +1,59 @@
+package com.baeldung.algorithms.prime;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class PrimeGenerator {
+ public static List sieveOfEratosthenes(int n) {
+ final boolean prime[] = new boolean[n + 1];
+ Arrays.fill(prime, true);
+
+ for (int p = 2; p * p <= n; p++) {
+ if (prime[p]) {
+ for (int i = p * 2; i <= n; i += p)
+ prime[i] = false;
+ }
+ }
+
+ final List primes = new LinkedList<>();
+ for (int i = 2; i <= n; i++) {
+ if (prime[i])
+ primes.add(i);
+ }
+ return primes;
+ }
+
+ public static List primeNumbersBruteForce(int max) {
+ final List primeNumbers = new LinkedList();
+ for (int i = 2; i <= max; i++) {
+ if (isPrimeBruteForce(i)) {
+ primeNumbers.add(i);
+ }
+ }
+ return primeNumbers;
+ }
+
+ private static boolean isPrimeBruteForce(int x) {
+ for (int i = 2; i < x; i++) {
+ if (x % i == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static List primeNumbersTill(int max) {
+ return IntStream.rangeClosed(2, max)
+ .filter(x -> isPrime(x))
+ .boxed()
+ .collect(Collectors.toList());
+ }
+
+ private static boolean isPrime(int x) {
+ return IntStream.rangeClosed(2, (int) (Math.sqrt(x)))
+ .allMatch(n -> x % n != 0);
+ }
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java
new file mode 100644
index 0000000000..4b37558aab
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java
@@ -0,0 +1,104 @@
+package com.baeldung.algorithms.sudoku;
+
+import java.util.stream.IntStream;
+
+public class BacktrackingAlgorithm {
+
+ private static final int BOARD_SIZE = 9;
+ private static final int SUBSECTION_SIZE = 3;
+ private static final int BOARD_START_INDEX = 0;
+
+ private static final int NO_VALUE = 0;
+ private static final int MIN_VALUE = 1;
+ private static final int MAX_VALUE = 9;
+
+ private static int[][] board = {
+ {8, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 3, 6, 0, 0, 0, 0, 0},
+ {0, 7, 0, 0, 9, 0, 2, 0, 0},
+ {0, 5, 0, 0, 0, 7, 0, 0, 0},
+ {0, 0, 0, 0, 4, 5, 7, 0, 0},
+ {0, 0, 0, 1, 0, 0, 0, 3, 0},
+ {0, 0, 1, 0, 0, 0, 0, 6, 8},
+ {0, 0, 8, 5, 0, 0, 0, 1, 0},
+ {0, 9, 0, 0, 0, 0, 4, 0, 0}
+ };
+
+ public static void main(String[] args) {
+ BacktrackingAlgorithm solver = new BacktrackingAlgorithm();
+ solver.solve(board);
+ solver.printBoard();
+ }
+
+ private void printBoard() {
+ for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
+ for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
+ System.out.print(board[row][column] + " ");
+ }
+ System.out.println();
+ }
+ }
+
+ private boolean solve(int[][] board) {
+ for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
+ for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
+ if (board[row][column] == NO_VALUE) {
+ for (int k = MIN_VALUE; k <= MAX_VALUE; k++) {
+ board[row][column] = k;
+ if (isValid(board, row, column) && solve(board)) {
+ return true;
+ }
+ board[row][column] = NO_VALUE;
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean isValid(int[][] board, int row, int column) {
+ return rowConstraint(board, row) &&
+ columnConstraint(board, column) &&
+ subsectionConstraint(board, row, column);
+ }
+
+ private boolean subsectionConstraint(int[][] board, int row, int column) {
+ boolean[] constraint = new boolean[BOARD_SIZE];
+ int subsectionRowStart = (row / SUBSECTION_SIZE) * SUBSECTION_SIZE;
+ int subsectionRowEnd = subsectionRowStart + SUBSECTION_SIZE;
+
+ int subsectionColumnStart = (column / SUBSECTION_SIZE) * SUBSECTION_SIZE;
+ int subsectionColumnEnd = subsectionColumnStart + SUBSECTION_SIZE;
+
+ for (int r = subsectionRowStart; r < subsectionRowEnd; r++) {
+ for (int c = subsectionColumnStart; c < subsectionColumnEnd; c++) {
+ if (!checkConstraint(board, r, constraint, c)) return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean columnConstraint(int[][] board, int column) {
+ boolean[] constraint = new boolean[BOARD_SIZE];
+ return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
+ .allMatch(row -> checkConstraint(board, row, constraint, column));
+ }
+
+ private boolean rowConstraint(int[][] board, int row) {
+ boolean[] constraint = new boolean[BOARD_SIZE];
+ return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
+ .allMatch(column -> checkConstraint(board, row, constraint, column));
+ }
+
+ private boolean checkConstraint(int[][] board, int row, boolean[] constraint, int column) {
+ if (board[row][column] != NO_VALUE) {
+ if (!constraint[board[row][column] - 1]) {
+ constraint[board[row][column] - 1] = true;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java
new file mode 100644
index 0000000000..46995ca42f
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java
@@ -0,0 +1,33 @@
+package com.baeldung.algorithms.sudoku;
+
+class ColumnNode extends DancingNode {
+ int size;
+ String name;
+
+ ColumnNode(String n) {
+ super();
+ size = 0;
+ name = n;
+ C = this;
+ }
+
+ void cover() {
+ unlinkLR();
+ for (DancingNode i = this.D; i != this; i = i.D) {
+ for (DancingNode j = i.R; j != i; j = j.R) {
+ j.unlinkUD();
+ j.C.size--;
+ }
+ }
+ }
+
+ void uncover() {
+ for (DancingNode i = this.U; i != this; i = i.U) {
+ for (DancingNode j = i.L; j != i; j = j.L) {
+ j.C.size++;
+ j.relinkUD();
+ }
+ }
+ relinkLR();
+ }
+}
\ No newline at end of file
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java
new file mode 100644
index 0000000000..d3cbb2bd02
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java
@@ -0,0 +1,133 @@
+package com.baeldung.algorithms.sudoku;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+public class DancingLinks {
+
+ private ColumnNode header;
+ private List answer;
+
+ private void search(int k) {
+ if (header.R == header) {
+ handleSolution(answer);
+ } else {
+ ColumnNode c = selectColumnNodeHeuristic();
+ c.cover();
+
+ for (DancingNode r = c.D; r != c; r = r.D) {
+ answer.add(r);
+
+ for (DancingNode j = r.R; j != r; j = j.R) {
+ j.C.cover();
+ }
+
+ search(k + 1);
+
+ r = answer.remove(answer.size() - 1);
+ c = r.C;
+
+ for (DancingNode j = r.L; j != r; j = j.L) {
+ j.C.uncover();
+ }
+ }
+ c.uncover();
+ }
+ }
+
+ private ColumnNode selectColumnNodeHeuristic() {
+ int min = Integer.MAX_VALUE;
+ ColumnNode ret = null;
+ for (ColumnNode c = (ColumnNode) header.R; c != header; c = (ColumnNode) c.R) {
+ if (c.size < min) {
+ min = c.size;
+ ret = c;
+ }
+ }
+ return ret;
+ }
+
+ private ColumnNode makeDLXBoard(boolean[][] grid) {
+ final int COLS = grid[0].length;
+
+ ColumnNode headerNode = new ColumnNode("header");
+ List columnNodes = new ArrayList<>();
+
+ for (int i = 0; i < COLS; i++) {
+ ColumnNode n = new ColumnNode(Integer.toString(i));
+ columnNodes.add(n);
+ headerNode = (ColumnNode) headerNode.hookRight(n);
+ }
+ headerNode = headerNode.R.C;
+
+ for (boolean[] aGrid : grid) {
+ DancingNode prev = null;
+ for (int j = 0; j < COLS; j++) {
+ if (aGrid[j]) {
+ ColumnNode col = columnNodes.get(j);
+ DancingNode newNode = new DancingNode(col);
+ if (prev == null)
+ prev = newNode;
+ col.U.hookDown(newNode);
+ prev = prev.hookRight(newNode);
+ col.size++;
+ }
+ }
+ }
+
+ headerNode.size = COLS;
+
+ return headerNode;
+ }
+
+ DancingLinks(boolean[][] cover) {
+ header = makeDLXBoard(cover);
+ }
+
+ public void runSolver() {
+ answer = new LinkedList<>();
+ search(0);
+ }
+
+ private void handleSolution(List answer) {
+ int[][] result = parseBoard(answer);
+ printSolution(result);
+ }
+
+ private int size = 9;
+
+ private int[][] parseBoard(List answer) {
+ int[][] result = new int[size][size];
+ for (DancingNode n : answer) {
+ DancingNode rcNode = n;
+ int min = Integer.parseInt(rcNode.C.name);
+ for (DancingNode tmp = n.R; tmp != n; tmp = tmp.R) {
+ int val = Integer.parseInt(tmp.C.name);
+ if (val < min) {
+ min = val;
+ rcNode = tmp;
+ }
+ }
+ int ans1 = Integer.parseInt(rcNode.C.name);
+ int ans2 = Integer.parseInt(rcNode.R.C.name);
+ int r = ans1 / size;
+ int c = ans1 % size;
+ int num = (ans2 % size) + 1;
+ result[r][c] = num;
+ }
+ return result;
+ }
+
+ private static void printSolution(int[][] result) {
+ int size = result.length;
+ for (int[] aResult : result) {
+ StringBuilder ret = new StringBuilder();
+ for (int j = 0; j < size; j++) {
+ ret.append(aResult[j]).append(" ");
+ }
+ System.out.println(ret);
+ }
+ System.out.println();
+ }
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java
new file mode 100644
index 0000000000..df02ff3d11
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java
@@ -0,0 +1,121 @@
+package com.baeldung.algorithms.sudoku;
+
+import java.util.Arrays;
+
+public class DancingLinksAlgorithm {
+ private static final int BOARD_SIZE = 9;
+ private static final int SUBSECTION_SIZE = 3;
+ private static final int NO_VALUE = 0;
+ private static final int CONSTRAINTS = 4;
+ private static final int MIN_VALUE = 1;
+ private static final int MAX_VALUE = 9;
+ private static final int COVER_START_INDEX = 1;
+
+ private static int[][] board = {
+ {8, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 3, 6, 0, 0, 0, 0, 0},
+ {0, 7, 0, 0, 9, 0, 2, 0, 0},
+ {0, 5, 0, 0, 0, 7, 0, 0, 0},
+ {0, 0, 0, 0, 4, 5, 7, 0, 0},
+ {0, 0, 0, 1, 0, 0, 0, 3, 0},
+ {0, 0, 1, 0, 0, 0, 0, 6, 8},
+ {0, 0, 8, 5, 0, 0, 0, 1, 0},
+ {0, 9, 0, 0, 0, 0, 4, 0, 0}
+ };
+
+ public static void main(String[] args) {
+ DancingLinksAlgorithm solver = new DancingLinksAlgorithm();
+ solver.solve(board);
+ }
+
+ private void solve(int[][] board) {
+ boolean[][] cover = initializeExactCoverBoard(board);
+ DancingLinks dlx = new DancingLinks(cover);
+ dlx.runSolver();
+ }
+
+ private int getIndex(int row, int column, int num) {
+ return (row - 1) * BOARD_SIZE * BOARD_SIZE + (column - 1) * BOARD_SIZE + (num - 1);
+ }
+
+ private boolean[][] createExactCoverBoard() {
+ boolean[][] coverBoard = new boolean[BOARD_SIZE * BOARD_SIZE * MAX_VALUE][BOARD_SIZE * BOARD_SIZE * CONSTRAINTS];
+
+ int hBase = 0;
+ hBase = checkCellConstraint(coverBoard, hBase);
+ hBase = checkRowConstraint(coverBoard, hBase);
+ hBase = checkColumnConstraint(coverBoard, hBase);
+ checkSubsectionConstraint(coverBoard, hBase);
+
+ return coverBoard;
+ }
+
+ private int checkSubsectionConstraint(boolean[][] coverBoard, int hBase) {
+ for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row += SUBSECTION_SIZE) {
+ for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column += SUBSECTION_SIZE) {
+ for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
+ for (int rowDelta = 0; rowDelta < SUBSECTION_SIZE; rowDelta++) {
+ for (int columnDelta = 0; columnDelta < SUBSECTION_SIZE; columnDelta++) {
+ int index = getIndex(row + rowDelta, column + columnDelta, n);
+ coverBoard[index][hBase] = true;
+ }
+ }
+ }
+ }
+ }
+ return hBase;
+ }
+
+ private int checkColumnConstraint(boolean[][] coverBoard, int hBase) {
+ for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
+ for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
+ for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
+ int index = getIndex(row, column, n);
+ coverBoard[index][hBase] = true;
+ }
+ }
+ }
+ return hBase;
+ }
+
+ private int checkRowConstraint(boolean[][] coverBoard, int hBase) {
+ for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
+ for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
+ for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
+ int index = getIndex(row, column, n);
+ coverBoard[index][hBase] = true;
+ }
+ }
+ }
+ return hBase;
+ }
+
+ private int checkCellConstraint(boolean[][] coverBoard, int hBase) {
+ for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
+ for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++, hBase++) {
+ for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++) {
+ int index = getIndex(row, column, n);
+ coverBoard[index][hBase] = true;
+ }
+ }
+ }
+ return hBase;
+ }
+
+ private boolean[][] initializeExactCoverBoard(int[][] board) {
+ boolean[][] coverBoard = createExactCoverBoard();
+ for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
+ for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
+ int n = board[row - 1][column - 1];
+ if (n != NO_VALUE) {
+ for (int num = MIN_VALUE; num <= MAX_VALUE; num++) {
+ if (num != n) {
+ Arrays.fill(coverBoard[getIndex(row, column, num)], false);
+ }
+ }
+ }
+ }
+ }
+ return coverBoard;
+ }
+}
\ No newline at end of file
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java
new file mode 100644
index 0000000000..2422ff0dff
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java
@@ -0,0 +1,50 @@
+package com.baeldung.algorithms.sudoku;
+
+class DancingNode {
+ DancingNode L, R, U, D;
+ ColumnNode C;
+
+ DancingNode hookDown(DancingNode node) {
+ assert (this.C == node.C);
+ node.D = this.D;
+ node.D.U = node;
+ node.U = this;
+ this.D = node;
+ return node;
+ }
+
+ DancingNode hookRight(DancingNode node) {
+ node.R = this.R;
+ node.R.L = node;
+ node.L = this;
+ this.R = node;
+ return node;
+ }
+
+ void unlinkLR() {
+ this.L.R = this.R;
+ this.R.L = this.L;
+ }
+
+ void relinkLR() {
+ this.L.R = this.R.L = this;
+ }
+
+ void unlinkUD() {
+ this.U.D = this.D;
+ this.D.U = this.U;
+ }
+
+ void relinkUD() {
+ this.U.D = this.D.U = this;
+ }
+
+ DancingNode() {
+ L = R = U = D = this;
+ }
+
+ DancingNode(ColumnNode c) {
+ this();
+ C = c;
+ }
+}
\ No newline at end of file
diff --git a/algorithms/src/main/resources/maze/maze1.txt b/algorithms/src/main/resources/maze/maze1.txt
new file mode 100644
index 0000000000..0a6309d25b
--- /dev/null
+++ b/algorithms/src/main/resources/maze/maze1.txt
@@ -0,0 +1,12 @@
+S ########
+# #
+# ### ## #
+# # # #
+# # # # #
+# ## #####
+# # #
+# # # # #
+##### ####
+# # E
+# # # #
+##########
\ No newline at end of file
diff --git a/algorithms/src/main/resources/maze/maze2.txt b/algorithms/src/main/resources/maze/maze2.txt
new file mode 100644
index 0000000000..22e6d0382a
--- /dev/null
+++ b/algorithms/src/main/resources/maze/maze2.txt
@@ -0,0 +1,22 @@
+S ##########################
+# # # #
+# # #### ############### #
+# # # # # #
+# # #### # # ###############
+# # # # # # #
+# # # #### ### ########### #
+# # # # # #
+# ################## #
+######### # # # # #
+# # #### # ####### # #
+# # ### ### # # # # #
+# # ## # ##### # #
+##### ####### # # # # #
+# # ## ## #### # #
+# ##### ####### # #
+# # ############
+####### ######### # #
+# # ######## #
+# ####### ###### ## # E
+# # # ## #
+############################
\ No newline at end of file
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java b/algorithms/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java
new file mode 100644
index 0000000000..6fbb7c163a
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java
@@ -0,0 +1,57 @@
+package com.baeldung.algorithms.kthlargest;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class FindKthLargestUnitTest {
+
+ private FindKthLargest findKthLargest;
+ private Integer[] arr = { 3, 7, 1, 2, 8, 10, 4, 5, 6, 9 };
+
+ @Before
+ public void setup() {
+ findKthLargest = new FindKthLargest();
+ }
+
+ @Test
+ public void givenIntArray_whenFindKthLargestBySorting_thenGetResult() {
+ int k = 3;
+ assertThat(findKthLargest.findKthLargestBySorting(arr, k)).isEqualTo(8);
+ }
+
+ @Test
+ public void givenIntArray_whenFindKthLargestBySortingDesc_thenGetResult() {
+ int k = 3;
+ assertThat(findKthLargest.findKthLargestBySortingDesc(arr, k)).isEqualTo(8);
+ }
+
+ @Test
+ public void givenIntArray_whenFindKthLargestByQuickSelect_thenGetResult() {
+ int k = 3;
+ int kthLargest = arr.length - k;
+ assertThat(findKthLargest.findKthElementByQuickSelect(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8);
+ }
+
+ @Test
+ public void givenIntArray_whenFindKthElementByQuickSelectIterative_thenGetResult() {
+ int k = 3;
+ int kthLargest = arr.length - k;
+ assertThat(findKthLargest.findKthElementByQuickSelectWithIterativePartition(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8);
+ }
+
+ @Test
+ public void givenIntArray_whenFindKthSmallestByQuickSelect_thenGetResult() {
+ int k = 3;
+ assertThat(findKthLargest.findKthElementByQuickSelect(arr, 0, arr.length - 1, k - 1)).isEqualTo(3);
+ }
+
+ @Test
+ public void givenIntArray_whenFindKthLargestByRandomizedQuickSelect_thenGetResult() {
+ int k = 3;
+ int kthLargest = arr.length - k;
+ assertThat(findKthLargest.findKthElementByRandomizedQuickSelect(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8);
+ }
+
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/moneywords/NumberWordConverterTest.java b/algorithms/src/test/java/com/baeldung/algorithms/moneywords/NumberWordConverterTest.java
new file mode 100644
index 0000000000..a4a169f158
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/moneywords/NumberWordConverterTest.java
@@ -0,0 +1,84 @@
+package com.baeldung.algorithms.moneywords;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.baeldung.algorithms.numberwordconverter.NumberWordConverter;
+
+public class NumberWordConverterTest {
+
+ @Test
+ public void whenMoneyNegative_thenReturnInvalidInput() {
+ assertEquals(NumberWordConverter.INVALID_INPUT_GIVEN, NumberWordConverter.getMoneyIntoWords(-13));
+ }
+
+ @Test
+ public void whenZeroDollarsGiven_thenReturnEmptyString() {
+ assertEquals("", NumberWordConverter.getMoneyIntoWords(0));
+ }
+
+ @Test
+ public void whenOnlyDollarsGiven_thenReturnWords() {
+ assertEquals("one dollar", NumberWordConverter.getMoneyIntoWords(1));
+ }
+
+ @Test
+ public void whenOnlyCentsGiven_thenReturnWords() {
+ assertEquals("sixty cents", NumberWordConverter.getMoneyIntoWords(0.6));
+ }
+
+ @Test
+ public void whenAlmostAMillioDollarsGiven_thenReturnWords() {
+ String expectedResult = "nine hundred ninety nine thousand nine hundred ninety nine dollars";
+ assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(999_999));
+ }
+
+ @Test
+ public void whenThirtyMillionDollarsGiven_thenReturnWords() {
+ String expectedResult = "thirty three million three hundred forty eight thousand nine hundred seventy eight dollars";
+ assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(33_348_978));
+ }
+
+ @Test
+ public void whenTwoBillionDollarsGiven_thenReturnWords() {
+ String expectedResult = "two billion one hundred thirty three million two hundred forty seven thousand eight hundred ten dollars";
+ assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(2_133_247_810));
+ }
+
+ @Test
+ public void whenGivenDollarsAndCents_thenReturnWords() {
+ String expectedResult = "nine hundred twenty four dollars and sixty cents";
+ assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(924.6));
+ }
+
+ @Test
+ public void whenOneDollarAndNoCents_thenReturnDollarSingular() {
+ assertEquals("one dollar", NumberWordConverter.getMoneyIntoWords(1));
+ }
+
+ @Test
+ public void whenNoDollarsAndOneCent_thenReturnCentSingular() {
+ assertEquals("one cent", NumberWordConverter.getMoneyIntoWords(0.01));
+ }
+
+ @Test
+ public void whenNoDollarsAndTwoCents_thenReturnCentsPlural() {
+ assertEquals("two cents", NumberWordConverter.getMoneyIntoWords(0.02));
+ }
+
+ @Test
+ public void whenNoDollarsAndNinetyNineCents_thenReturnWords() {
+ assertEquals("ninety nine cents", NumberWordConverter.getMoneyIntoWords(0.99));
+ }
+
+ @Test
+ public void whenNoDollarsAndNineFiveNineCents_thenCorrectRounding() {
+ assertEquals("ninety six cents", NumberWordConverter.getMoneyIntoWords(0.959));
+ }
+
+ @Test
+ public void whenGivenDollarsAndCents_thenReturnWordsVersionTwo() {
+ assertEquals("three hundred ten £ 00/100", NumberWordConverter.getMoneyIntoWords("310"));
+ }
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/multiswarm/LolFitnessFunction.java b/algorithms/src/test/java/com/baeldung/algorithms/multiswarm/LolFitnessFunction.java
new file mode 100644
index 0000000000..726d4c135d
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/multiswarm/LolFitnessFunction.java
@@ -0,0 +1,52 @@
+package com.baeldung.algorithms.multiswarm;
+
+/**
+ * Specific fitness function implementation to solve the League of Legends
+ * problem. This is the problem statement:
+ *
+ * In League of Legends, a player's Effective Health when defending against
+ * physical damage is given by E=H(100+A)/100, where H is health and A is armor.
+ * Health costs 2.5 gold per unit, and Armor costs 18 gold per unit. You have
+ * 3600 gold, and you need to optimize the effectiveness E of your health and
+ * armor to survive as long as possible against the enemy team's attacks. How
+ * much of each should you buy?
+ *
+ *
+ * @author Donato Rimenti
+ *
+ */
+public class LolFitnessFunction implements FitnessFunction {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.baeldung.algorithms.multiswarm.FitnessFunction#getFitness(long[])
+ */
+ @Override
+ public double getFitness(long[] particlePosition) {
+
+ long health = particlePosition[0];
+ long armor = particlePosition[1];
+
+ // No negatives values accepted.
+ if (health < 0 && armor < 0) {
+ return -(health * armor);
+ } else if (health < 0) {
+ return health;
+ } else if (armor < 0) {
+ return armor;
+ }
+
+ // Checks if the solution is actually feasible provided our gold.
+ double cost = (health * 2.5) + (armor * 18);
+ if (cost > 3600) {
+ return 3600 - cost;
+ } else {
+ // Check how good is the solution.
+ long fitness = (health * (100 + armor)) / 100;
+ return fitness;
+ }
+ }
+
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/multiswarm/MultiswarmUnitTest.java b/algorithms/src/test/java/com/baeldung/algorithms/multiswarm/MultiswarmUnitTest.java
new file mode 100644
index 0000000000..3455cd3932
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/multiswarm/MultiswarmUnitTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.algorithms.multiswarm;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.baeldung.algorithms.support.MayFailRule;
+
+/**
+ * Test for {@link Multiswarm}.
+ *
+ * @author Donato Rimenti
+ *
+ */
+public class MultiswarmUnitTest {
+
+ /**
+ * Rule for handling expected failures. We use this since this test may
+ * actually fail due to bad luck in the random generation.
+ */
+ @Rule
+ public MayFailRule mayFailRule = new MayFailRule();
+
+ /**
+ * Tests the multiswarm algorithm with a generic problem. The problem is the
+ * following:
+ *
+ * In League of Legends, a player's Effective Health when defending against
+ * physical damage is given by E=H(100+A)/100, where H is health and A is
+ * armor. Health costs 2.5 gold per unit, and Armor costs 18 gold per unit.
+ * You have 3600 gold, and you need to optimize the effectiveness E of your
+ * health and armor to survive as long as possible against the enemy team's
+ * attacks. How much of each should you buy?
+ *
+ * The solution is H = 1080, A = 50 for a total fitness of 1620. Tested with
+ * 50 swarms each with 1000 particles.
+ */
+ @Test
+ public void givenMultiswarm_whenThousandIteration_thenSolutionFound() {
+ Multiswarm multiswarm = new Multiswarm(50, 1000, new LolFitnessFunction());
+
+ // Iterates 1000 times through the main loop and prints the result.
+ for (int i = 0; i < 1000; i++) {
+ multiswarm.mainLoop();
+ }
+
+ System.out.println("Best fitness found: " + multiswarm.getBestFitness() + "[" + multiswarm.getBestPosition()[0]
+ + "," + multiswarm.getBestPosition()[1] + "]");
+ Assert.assertEquals(1080, multiswarm.getBestPosition()[0]);
+ Assert.assertEquals(50, multiswarm.getBestPosition()[1]);
+ Assert.assertEquals(1620, (int) multiswarm.getBestFitness());
+ }
+
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/prime/PrimeGeneratorTest.java b/algorithms/src/test/java/com/baeldung/algorithms/prime/PrimeGeneratorTest.java
new file mode 100644
index 0000000000..4995e938b7
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/prime/PrimeGeneratorTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.algorithms.prime;
+
+import static com.baeldung.algorithms.prime.PrimeGenerator.*;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class PrimeGeneratorTest {
+ @Test
+ public void whenBruteForced_returnsSuccessfully() {
+ final List primeNumbers = primeNumbersBruteForce(20);
+ assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
+ }
+
+ @Test
+ public void whenOptimized_returnsSuccessfully() {
+ final List primeNumbers = primeNumbersTill(20);
+ assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
+ }
+
+ @Test
+ public void whenSieveOfEratosthenes_returnsSuccessfully() {
+ final List primeNumbers = sieveOfEratosthenes(20);
+ assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
+ }
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/support/MayFailRule.java b/algorithms/src/test/java/com/baeldung/algorithms/support/MayFailRule.java
new file mode 100644
index 0000000000..91df78ce4a
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/support/MayFailRule.java
@@ -0,0 +1,38 @@
+package com.baeldung.algorithms.support;
+
+import org.junit.Rule;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit custom rule for managing tests that may fail due to heuristics or
+ * randomness. In order to use this, just instantiate this object as a public
+ * field inside the test class and annotate it with {@link Rule}.
+ *
+ * @author Donato Rimenti
+ *
+ */
+public class MayFailRule implements TestRule {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.junit.rules.TestRule#apply(org.junit.runners.model.Statement,
+ * org.junit.runner.Description)
+ */
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ try {
+ base.evaluate();
+ } catch (Throwable e) {
+ // Ignore the exception since we expect this.
+ }
+ }
+ };
+ }
+
+}
diff --git a/animal-sniffer-mvn-plugin/pom.xml b/animal-sniffer-mvn-plugin/pom.xml
index 3190950d9b..2356c7d5a2 100644
--- a/animal-sniffer-mvn-plugin/pom.xml
+++ b/animal-sniffer-mvn-plugin/pom.xml
@@ -9,7 +9,7 @@
http://maven.apache.org
- 3.6.0
+ 3.7.0
@@ -26,8 +26,8 @@
maven-compiler-plugin
3.7.0
- 1.6
- 1.6
+ 1.8
+ 1.8
diff --git a/annotations/annotation-processing/pom.xml b/annotations/annotation-processing/pom.xml
index df6f9d44b7..b5219d57ba 100644
--- a/annotations/annotation-processing/pom.xml
+++ b/annotations/annotation-processing/pom.xml
@@ -15,7 +15,7 @@
1.0-rc2
- 3.6.0
+ 3.7.0
diff --git a/apache-curator/pom.xml b/apache-curator/pom.xml
new file mode 100644
index 0000000000..35549861c8
--- /dev/null
+++ b/apache-curator/pom.xml
@@ -0,0 +1,76 @@
+
+ 4.0.0
+ apache-curator
+ 0.0.1-SNAPSHOT
+ jar
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+ 4.0.1
+ 3.4.11
+ 2.9.4
+
+
+ 3.6.1
+ 1.7.0
+
+
+
+
+
+
+
+
+ org.apache.curator
+ curator-x-async
+ ${curator.version}
+
+
+ org.apache.zookeeper
+ zookeeper
+
+
+
+
+
+ org.apache.curator
+ curator-recipes
+ ${curator.version}
+
+
+
+ org.apache.zookeeper
+ zookeeper
+ ${zookeeper.version}
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson-databind.version}
+
+
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+
+ com.jayway.awaitility
+ awaitility
+ ${avaitility.version}
+ test
+
+
+
diff --git a/apache-curator/src/main/java/com/baeldung/apache/curator/modeled/HostConfig.java b/apache-curator/src/main/java/com/baeldung/apache/curator/modeled/HostConfig.java
new file mode 100644
index 0000000000..bab7133742
--- /dev/null
+++ b/apache-curator/src/main/java/com/baeldung/apache/curator/modeled/HostConfig.java
@@ -0,0 +1,31 @@
+package com.baeldung.apache.curator.modeled;
+
+public class HostConfig {
+ private String hostname;
+ private int port;
+
+ public HostConfig() {
+
+ }
+
+ public HostConfig(String hostname, int port) {
+ this.hostname = hostname;
+ this.port = port;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+}
diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/BaseTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/BaseTest.java
new file mode 100644
index 0000000000..cfac3ee3f2
--- /dev/null
+++ b/apache-curator/src/test/java/com/baeldung/apache/curator/BaseTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.apache.curator;
+
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.RetryNTimes;
+import org.junit.Before;
+
+public abstract class BaseTest {
+
+ @Before
+ public void setup() {
+ org.apache.log4j.BasicConfigurator.configure();
+ }
+
+ protected CuratorFramework newClient() {
+ int sleepMsBetweenRetries = 100;
+ int maxRetries = 3;
+ RetryPolicy retryPolicy = new RetryNTimes(maxRetries, sleepMsBetweenRetries);
+ return CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
+ }
+}
diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/configuration/ConfigurationManagementManualTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/configuration/ConfigurationManagementManualTest.java
new file mode 100644
index 0000000000..d02ef8131d
--- /dev/null
+++ b/apache-curator/src/test/java/com/baeldung/apache/curator/configuration/ConfigurationManagementManualTest.java
@@ -0,0 +1,89 @@
+package com.baeldung.apache.curator.configuration;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.junit.Test;
+
+import com.baeldung.apache.curator.BaseTest;
+
+public class ConfigurationManagementManualTest extends BaseTest {
+
+ private static final String KEY_FORMAT = "/%s";
+
+ @Test
+ public void givenPath_whenCreateKey_thenValueIsStored() throws Exception {
+ try (CuratorFramework client = newClient()) {
+ client.start();
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+ String key = getKey();
+ String expected = "my_value";
+
+ // Create key nodes structure
+ client.create()
+ .forPath(key);
+
+ // Set data value for our key
+ async.setData()
+ .forPath(key, expected.getBytes());
+
+ // Get data value
+ AtomicBoolean isEquals = new AtomicBoolean();
+ async.getData()
+ .forPath(key)
+ .thenAccept(
+ data -> isEquals.set(new String(data).equals(expected)));
+
+ await().until(() -> assertThat(isEquals.get()).isTrue());
+ }
+ }
+
+ @Test
+ public void givenPath_whenWatchAKeyAndStoreAValue_thenWatcherIsTriggered()
+ throws Exception {
+ try (CuratorFramework client = newClient()) {
+ client.start();
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+ String key = getKey();
+ String expected = "my_value";
+
+ // Create key structure
+ async.create()
+ .forPath(key);
+
+ List changes = new ArrayList<>();
+
+ // Watch data value
+ async.watched()
+ .getData()
+ .forPath(key)
+ .event()
+ .thenAccept(watchedEvent -> {
+ try {
+ changes.add(new String(client.getData()
+ .forPath(watchedEvent.getPath())));
+ } catch (Exception e) {
+ // fail ...
+ }
+ });
+
+ // Set data value for our key
+ async.setData()
+ .forPath(key, expected.getBytes());
+
+ await().until(() -> assertThat(changes.size() > 0).isTrue());
+ }
+ }
+
+ private String getKey() {
+ return String.format(KEY_FORMAT, UUID.randomUUID()
+ .toString());
+ }
+}
diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/connection/ConnectionManagementManualTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/connection/ConnectionManagementManualTest.java
new file mode 100644
index 0000000000..61fa1c7c2c
--- /dev/null
+++ b/apache-curator/src/test/java/com/baeldung/apache/curator/connection/ConnectionManagementManualTest.java
@@ -0,0 +1,79 @@
+package com.baeldung.apache.curator.connection;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.curator.RetryPolicy;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.RetryNTimes;
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.junit.Test;
+
+public class ConnectionManagementManualTest {
+
+ @Test
+ public void givenRunningZookeeper_whenOpenConnection_thenClientIsOpened()
+ throws Exception {
+ int sleepMsBetweenRetries = 100;
+ int maxRetries = 3;
+ RetryPolicy retryPolicy = new RetryNTimes(maxRetries,
+ sleepMsBetweenRetries);
+
+ try (CuratorFramework client = CuratorFrameworkFactory
+ .newClient("127.0.0.1:2181", retryPolicy)) {
+ client.start();
+
+ assertThat(client.checkExists()
+ .forPath("/")).isNotNull();
+ }
+ }
+
+ @Test
+ public void givenRunningZookeeper_whenOpenConnectionUsingAsyncNotBlocking_thenClientIsOpened()
+ throws InterruptedException {
+ int sleepMsBetweenRetries = 100;
+ int maxRetries = 3;
+ RetryPolicy retryPolicy = new RetryNTimes(maxRetries,
+ sleepMsBetweenRetries);
+
+ try (CuratorFramework client = CuratorFrameworkFactory
+ .newClient("127.0.0.1:2181", retryPolicy)) {
+ client.start();
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+
+ AtomicBoolean exists = new AtomicBoolean(false);
+
+ async.checkExists()
+ .forPath("/")
+ .thenAcceptAsync(s -> exists.set(s != null));
+
+ await().until(() -> assertThat(exists.get()).isTrue());
+ }
+ }
+
+ @Test
+ public void givenRunningZookeeper_whenOpenConnectionUsingAsyncBlocking_thenClientIsOpened()
+ throws InterruptedException {
+ int sleepMsBetweenRetries = 100;
+ int maxRetries = 3;
+ RetryPolicy retryPolicy = new RetryNTimes(maxRetries,
+ sleepMsBetweenRetries);
+
+ try (CuratorFramework client = CuratorFrameworkFactory
+ .newClient("127.0.0.1:2181", retryPolicy)) {
+ client.start();
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+
+ AtomicBoolean exists = new AtomicBoolean(false);
+
+ async.checkExists()
+ .forPath("/")
+ .thenAccept(s -> exists.set(s != null));
+
+ await().until(() -> assertThat(exists.get()).isTrue());
+ }
+ }
+}
diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/modeled/ModelTypedExamplesManualTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/modeled/ModelTypedExamplesManualTest.java
new file mode 100644
index 0000000000..4400c1d1aa
--- /dev/null
+++ b/apache-curator/src/test/java/com/baeldung/apache/curator/modeled/ModelTypedExamplesManualTest.java
@@ -0,0 +1,49 @@
+package com.baeldung.apache.curator.modeled;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.x.async.AsyncCuratorFramework;
+import org.apache.curator.x.async.modeled.JacksonModelSerializer;
+import org.apache.curator.x.async.modeled.ModelSpec;
+import org.apache.curator.x.async.modeled.ModeledFramework;
+import org.apache.curator.x.async.modeled.ZPath;
+import org.junit.Test;
+
+import com.baeldung.apache.curator.BaseTest;
+
+public class ModelTypedExamplesManualTest extends BaseTest {
+
+ @Test
+ public void givenPath_whenStoreAModel_thenNodesAreCreated()
+ throws InterruptedException {
+
+ ModelSpec mySpec = ModelSpec
+ .builder(ZPath.parseWithIds("/config/dev"),
+ JacksonModelSerializer.build(HostConfig.class))
+ .build();
+
+ try (CuratorFramework client = newClient()) {
+ client.start();
+ AsyncCuratorFramework async = AsyncCuratorFramework.wrap(client);
+ ModeledFramework modeledClient = ModeledFramework
+ .wrap(async, mySpec);
+
+ modeledClient.set(new HostConfig("host-name", 8080));
+
+ modeledClient.read()
+ .whenComplete((value, e) -> {
+ if (e != null) {
+ fail("Cannot read host config", e);
+ } else {
+ assertThat(value).isNotNull();
+ assertThat(value.getHostname()).isEqualTo("host-name");
+ assertThat(value.getPort()).isEqualTo(8080);
+ }
+
+ });
+ }
+
+ }
+}
diff --git a/apache-curator/src/test/java/com/baeldung/apache/curator/recipes/RecipesManualTest.java b/apache-curator/src/test/java/com/baeldung/apache/curator/recipes/RecipesManualTest.java
new file mode 100644
index 0000000000..04f4104e6b
--- /dev/null
+++ b/apache-curator/src/test/java/com/baeldung/apache/curator/recipes/RecipesManualTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.apache.curator.recipes;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.recipes.leader.LeaderSelector;
+import org.apache.curator.framework.recipes.leader.LeaderSelectorListener;
+import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;
+import org.apache.curator.framework.recipes.shared.SharedCount;
+import org.apache.curator.framework.state.ConnectionState;
+import org.junit.Test;
+
+import com.baeldung.apache.curator.BaseTest;
+
+public class RecipesManualTest extends BaseTest {
+
+ @Test
+ public void givenRunningZookeeper_whenUsingLeaderElection_thenNoErrors() {
+ try (CuratorFramework client = newClient()) {
+ client.start();
+ LeaderSelector leaderSelector = new LeaderSelector(client, "/mutex/select/leader/for/job/A", new LeaderSelectorListener() {
+
+ @Override
+ public void stateChanged(CuratorFramework client, ConnectionState newState) {
+
+ }
+
+ @Override
+ public void takeLeadership(CuratorFramework client) throws Exception {
+ // I'm the leader of the job A !
+ }
+
+ });
+
+ leaderSelector.start();
+
+ // Wait until the job A is done among all the members
+
+ leaderSelector.close();
+ }
+ }
+
+ @Test
+ public void givenRunningZookeeper_whenUsingSharedLock_thenNoErrors() throws Exception {
+ try (CuratorFramework client = newClient()) {
+ client.start();
+ InterProcessSemaphoreMutex sharedLock = new InterProcessSemaphoreMutex(client, "/mutex/process/A");
+
+ sharedLock.acquire();
+
+ // Do process A
+
+ sharedLock.release();
+ }
+ }
+
+ @Test
+ public void givenRunningZookeeper_whenUsingSharedCounter_thenCounterIsIncrement() throws Exception {
+ try (CuratorFramework client = newClient()) {
+ client.start();
+
+ try (SharedCount counter = new SharedCount(client, "/counters/A", 0)) {
+ counter.start();
+
+ counter.setCount(0);
+ counter.setCount(counter.getCount() + 1);
+
+ assertThat(counter.getCount()).isEqualTo(1);
+ }
+
+ }
+ }
+
+}
diff --git a/apache-poi/README.md b/apache-poi/README.md
index 10fe8ba2e7..c052bc9bf6 100644
--- a/apache-poi/README.md
+++ b/apache-poi/README.md
@@ -1,3 +1,4 @@
### Relevant Articles:
- [Microsoft Word Processing in Java with Apache POI](http://www.baeldung.com/java-microsoft-word-with-apache-poi)
- [Working with Microsoft Excel in Java](http://www.baeldung.com/java-microsoft-excel)
+- [Creating a MS PowerPoint Presentation in Java](https://github.com/eugenp/tutorials/tree/master/apache-poi)
diff --git a/apache-poi/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java b/apache-poi/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java
new file mode 100644
index 0000000000..e2af4f8808
--- /dev/null
+++ b/apache-poi/src/main/java/com/baeldung/poi/powerpoint/PowerPointHelper.java
@@ -0,0 +1,224 @@
+package com.baeldung.poi.powerpoint;
+
+import org.apache.poi.sl.usermodel.AutoNumberingScheme;
+import org.apache.poi.sl.usermodel.PictureData;
+import org.apache.poi.sl.usermodel.TableCell;
+import org.apache.poi.sl.usermodel.TextParagraph;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xslf.usermodel.*;
+
+import java.awt.*;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper class for the PowerPoint presentation creation
+ */
+public class PowerPointHelper {
+
+ /**
+ * Read an existing presentation
+ *
+ * @param fileLocation
+ * File location of the presentation
+ * @return instance of {@link XMLSlideShow}
+ * @throws IOException
+ */
+ public XMLSlideShow readingExistingSlideShow(String fileLocation) throws IOException {
+ return new XMLSlideShow(new FileInputStream(fileLocation));
+ }
+
+ /**
+ * Create a sample presentation
+ *
+ * @param fileLocation
+ * File location of the presentation
+ * @throws IOException
+ */
+ public void createPresentation(String fileLocation) throws IOException {
+ // Create presentation
+ XMLSlideShow ppt = new XMLSlideShow();
+
+ XSLFSlideMaster defaultMaster = ppt.getSlideMasters().get(0);
+
+ // Retriving the slide layout
+ XSLFSlideLayout layout = defaultMaster.getLayout(SlideLayout.TITLE_ONLY);
+
+ // Creating the 1st slide
+ XSLFSlide slide1 = ppt.createSlide(layout);
+ XSLFTextShape title = slide1.getPlaceholder(0);
+ // Clearing text to remove the predefined one in the template
+ title.clearText();
+ XSLFTextParagraph p = title.addNewTextParagraph();
+
+ XSLFTextRun r1 = p.addNewTextRun();
+ r1.setText("Baeldung");
+ r1.setFontColor(new Color(78, 147, 89));
+ r1.setFontSize(48.);
+
+ // Add Image
+ ClassLoader classLoader = getClass().getClassLoader();
+ byte[] pictureData = IOUtils.toByteArray(new FileInputStream(classLoader.getResource("logo-leaf.png").getFile()));
+
+ XSLFPictureData pd = ppt.addPicture(pictureData, PictureData.PictureType.PNG);
+ XSLFPictureShape picture = slide1.createPicture(pd);
+ picture.setAnchor(new Rectangle(320, 230, 100, 92));
+
+ // Creating 2nd slide
+ layout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT);
+ XSLFSlide slide2 = ppt.createSlide(layout);
+
+ // setting the tile
+ title = slide2.getPlaceholder(0);
+ title.clearText();
+ XSLFTextRun r = title.addNewTextParagraph().addNewTextRun();
+ r.setText("Baeldung");
+
+ // Adding the link
+ XSLFHyperlink link = r.createHyperlink();
+ link.setAddress("http://www.baeldung.com");
+
+ // setting the content
+ XSLFTextShape content = slide2.getPlaceholder(1);
+ content.clearText(); // unset any existing text
+ content.addNewTextParagraph().addNewTextRun().setText("First paragraph");
+ content.addNewTextParagraph().addNewTextRun().setText("Second paragraph");
+ content.addNewTextParagraph().addNewTextRun().setText("Third paragraph");
+
+ // Creating 3rd slide - List
+ layout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT);
+ XSLFSlide slide3 = ppt.createSlide(layout);
+ title = slide3.getPlaceholder(0);
+ title.clearText();
+ r = title.addNewTextParagraph().addNewTextRun();
+ r.setText("Lists");
+
+ content = slide3.getPlaceholder(1);
+ content.clearText();
+ XSLFTextParagraph p1 = content.addNewTextParagraph();
+ p1.setIndentLevel(0);
+ p1.setBullet(true);
+ r1 = p1.addNewTextRun();
+ r1.setText("Bullet");
+
+ // the next three paragraphs form an auto-numbered list
+ XSLFTextParagraph p2 = content.addNewTextParagraph();
+ p2.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 1);
+ p2.setIndentLevel(1);
+ XSLFTextRun r2 = p2.addNewTextRun();
+ r2.setText("Numbered List Item - 1");
+
+ // Creating 4th slide
+ XSLFSlide slide4 = ppt.createSlide();
+ createTable(slide4);
+
+ // Save presentation
+ FileOutputStream out = new FileOutputStream(fileLocation);
+ ppt.write(out);
+ out.close();
+
+ // Closing presentation
+ ppt.close();
+ }
+
+ /**
+ * Delete a slide from the presentation
+ *
+ * @param ppt
+ * The presentation
+ * @param slideNumber
+ * The number of the slide to be deleted (0-based)
+ */
+ public void deleteSlide(XMLSlideShow ppt, int slideNumber) {
+ ppt.removeSlide(slideNumber);
+ }
+
+ /**
+ * Re-order the slides inside a presentation
+ *
+ * @param ppt
+ * The presentation
+ * @param slideNumber
+ * The number of the slide to move
+ * @param newSlideNumber
+ * The new position of the slide (0-base)
+ */
+ public void reorderSlide(XMLSlideShow ppt, int slideNumber, int newSlideNumber) {
+ List slides = ppt.getSlides();
+
+ XSLFSlide secondSlide = slides.get(slideNumber);
+ ppt.setSlideOrder(secondSlide, newSlideNumber);
+ }
+
+ /**
+ * Retrieve the placeholder inside a slide
+ *
+ * @param slide
+ * The slide
+ * @return List of placeholder inside a slide
+ */
+ public List retrieveTemplatePlaceholders(XSLFSlide slide) {
+ List placeholders = new ArrayList<>();
+
+ for (XSLFShape shape : slide.getShapes()) {
+ if (shape instanceof XSLFAutoShape) {
+ placeholders.add(shape);
+ }
+ }
+ return placeholders;
+ }
+
+ /**
+ * Create a table
+ *
+ * @param slide
+ * Slide
+ */
+ private void createTable(XSLFSlide slide) {
+
+ XSLFTable tbl = slide.createTable();
+ tbl.setAnchor(new Rectangle(50, 50, 450, 300));
+
+ int numColumns = 3;
+ int numRows = 5;
+
+ // header
+ XSLFTableRow headerRow = tbl.addRow();
+ headerRow.setHeight(50);
+ for (int i = 0; i < numColumns; i++) {
+ XSLFTableCell th = headerRow.addCell();
+ XSLFTextParagraph p = th.addNewTextParagraph();
+ p.setTextAlign(TextParagraph.TextAlign.CENTER);
+ XSLFTextRun r = p.addNewTextRun();
+ r.setText("Header " + (i + 1));
+ r.setBold(true);
+ r.setFontColor(Color.white);
+ th.setFillColor(new Color(79, 129, 189));
+ th.setBorderWidth(TableCell.BorderEdge.bottom, 2.0);
+ th.setBorderColor(TableCell.BorderEdge.bottom, Color.white);
+ // all columns are equally sized
+ tbl.setColumnWidth(i, 150);
+ }
+
+ // data
+ for (int rownum = 0; rownum < numRows; rownum++) {
+ XSLFTableRow tr = tbl.addRow();
+ tr.setHeight(50);
+ for (int i = 0; i < numColumns; i++) {
+ XSLFTableCell cell = tr.addCell();
+ XSLFTextParagraph p = cell.addNewTextParagraph();
+ XSLFTextRun r = p.addNewTextRun();
+
+ r.setText("Cell " + (i * rownum + 1));
+ if (rownum % 2 == 0) {
+ cell.setFillColor(new Color(208, 216, 232));
+ } else {
+ cell.setFillColor(new Color(233, 247, 244));
+ }
+ }
+ }
+ }
+}
diff --git a/apache-poi/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java b/apache-poi/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java
new file mode 100644
index 0000000000..5319208e85
--- /dev/null
+++ b/apache-poi/src/test/java/com/baeldung/poi/powerpoint/PowerPointIntegrationTest.java
@@ -0,0 +1,77 @@
+package com.baeldung.poi.powerpoint;
+
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFShape;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.List;
+
+public class PowerPointIntegrationTest {
+
+ private PowerPointHelper pph;
+ private String fileLocation;
+ private static final String FILE_NAME = "presentation.pptx";
+
+ @Before
+ public void setUp() throws Exception {
+ File currDir = new File(".");
+ String path = currDir.getAbsolutePath();
+ fileLocation = path.substring(0, path.length() - 1) + FILE_NAME;
+
+ pph = new PowerPointHelper();
+ pph.createPresentation(fileLocation);
+ }
+
+ @Test
+ public void whenReadingAPresentation_thenOK() throws Exception {
+ XMLSlideShow xmlSlideShow = pph.readingExistingSlideShow(fileLocation);
+
+ Assert.assertNotNull(xmlSlideShow);
+ Assert.assertEquals(4, xmlSlideShow.getSlides().size());
+ }
+
+ @Test
+ public void whenRetrievingThePlaceholdersForEachSlide_thenOK() throws Exception {
+ XMLSlideShow xmlSlideShow = pph.readingExistingSlideShow(fileLocation);
+
+ List onlyTitleSlidePlaceholders = pph.retrieveTemplatePlaceholders(xmlSlideShow.getSlides().get(0));
+ List titleAndBodySlidePlaceholders = pph.retrieveTemplatePlaceholders(xmlSlideShow.getSlides().get(1));
+ List emptySlidePlaceholdes = pph.retrieveTemplatePlaceholders(xmlSlideShow.getSlides().get(3));
+
+ Assert.assertEquals(1, onlyTitleSlidePlaceholders.size());
+ Assert.assertEquals(2, titleAndBodySlidePlaceholders.size());
+ Assert.assertEquals(0, emptySlidePlaceholdes.size());
+
+ }
+
+ @Test
+ public void whenSortingSlides_thenOK() throws Exception {
+ XMLSlideShow xmlSlideShow = pph.readingExistingSlideShow(fileLocation);
+ XSLFSlide slide4 = xmlSlideShow.getSlides().get(3);
+ pph.reorderSlide(xmlSlideShow, 3, 1);
+
+ Assert.assertEquals(slide4, xmlSlideShow.getSlides().get(1));
+ }
+
+ @Test
+ public void givenPresentation_whenDeletingASlide_thenOK() throws Exception {
+ XMLSlideShow xmlSlideShow = pph.readingExistingSlideShow(fileLocation);
+ pph.deleteSlide(xmlSlideShow, 3);
+
+ Assert.assertEquals(3, xmlSlideShow.getSlides().size());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ File testFile = new File(fileLocation);
+ if (testFile.exists()) {
+ testFile.delete();
+ }
+ pph = null;
+ }
+}
diff --git a/apache-shiro/pom.xml b/apache-shiro/pom.xml
index 711ddb5cee..2c5ef86837 100644
--- a/apache-shiro/pom.xml
+++ b/apache-shiro/pom.xml
@@ -65,7 +65,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.6.2
+ 3.7.0
1.8
1.8
diff --git a/apache-spark/README.md b/apache-spark/README.md
new file mode 100644
index 0000000000..fb8059eb27
--- /dev/null
+++ b/apache-spark/README.md
@@ -0,0 +1,3 @@
+### Relevant articles
+
+- [Introduction to Apache Spark](http://www.baeldung.com/apache-spark)
diff --git a/apache-tika/pom.xml b/apache-tika/pom.xml
new file mode 100644
index 0000000000..34013dee89
--- /dev/null
+++ b/apache-tika/pom.xml
@@ -0,0 +1,25 @@
+
+ 4.0.0
+ com.baeldung
+ apache-tika
+ 0.0.1-SNAPSHOT
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+ 1.17
+
+
+
+
+ org.apache.tika
+ tika-parsers
+ ${tika.version}
+
+
+
\ No newline at end of file
diff --git a/apache-tika/src/main/java/com/baeldung/tika/TikaAnalysis.java b/apache-tika/src/main/java/com/baeldung/tika/TikaAnalysis.java
new file mode 100644
index 0000000000..85eafc7c08
--- /dev/null
+++ b/apache-tika/src/main/java/com/baeldung/tika/TikaAnalysis.java
@@ -0,0 +1,67 @@
+package com.baeldung.tika;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.tika.Tika;
+import org.apache.tika.detect.DefaultDetector;
+import org.apache.tika.detect.Detector;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.AutoDetectParser;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.parser.Parser;
+import org.apache.tika.sax.BodyContentHandler;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+public class TikaAnalysis {
+ public static String detectDocTypeUsingDetector(InputStream stream) throws IOException {
+ Detector detector = new DefaultDetector();
+ Metadata metadata = new Metadata();
+
+ MediaType mediaType = detector.detect(stream, metadata);
+ return mediaType.toString();
+ }
+
+ public static String detectDocTypeUsingFacade(InputStream stream) throws IOException {
+ Tika tika = new Tika();
+ String mediaType = tika.detect(stream);
+ return mediaType;
+ }
+
+ public static String extractContentUsingParser(InputStream stream) throws IOException, TikaException, SAXException {
+ Parser parser = new AutoDetectParser();
+ ContentHandler handler = new BodyContentHandler();
+ Metadata metadata = new Metadata();
+ ParseContext context = new ParseContext();
+
+ parser.parse(stream, handler, metadata, context);
+ return handler.toString();
+ }
+
+ public static String extractContentUsingFacade(InputStream stream) throws IOException, TikaException {
+ Tika tika = new Tika();
+ String content = tika.parseToString(stream);
+ return content;
+ }
+
+ public static Metadata extractMetadatatUsingParser(InputStream stream) throws IOException, SAXException, TikaException {
+ Parser parser = new AutoDetectParser();
+ ContentHandler handler = new BodyContentHandler();
+ Metadata metadata = new Metadata();
+ ParseContext context = new ParseContext();
+
+ parser.parse(stream, handler, metadata, context);
+ return metadata;
+ }
+
+ public static Metadata extractMetadatatUsingFacade(InputStream stream) throws IOException, TikaException {
+ Tika tika = new Tika();
+ Metadata metadata = new Metadata();
+
+ tika.parse(stream, metadata);
+ return metadata;
+ }
+}
diff --git a/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java b/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java
new file mode 100644
index 0000000000..f8c2372d1f
--- /dev/null
+++ b/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java
@@ -0,0 +1,79 @@
+package com.baeldung.tika;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+public class TikaUnitTest {
+ @Test
+ public void whenUsingDetector_thenDocumentTypeIsReturned() throws IOException {
+ InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.txt");
+ String mediaType = TikaAnalysis.detectDocTypeUsingDetector(stream);
+
+ assertEquals("application/pdf", mediaType);
+
+ stream.close();
+ }
+
+ @Test
+ public void whenUsingFacade_thenDocumentTypeIsReturned() throws IOException {
+ InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.txt");
+ String mediaType = TikaAnalysis.detectDocTypeUsingFacade(stream);
+
+ assertEquals("application/pdf", mediaType);
+
+ stream.close();
+ }
+
+ @Test
+ public void whenUsingParser_thenContentIsReturned() throws IOException, TikaException, SAXException {
+ InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.docx");
+ String content = TikaAnalysis.extractContentUsingParser(stream);
+
+ assertThat(content, containsString("Apache Tika - a content analysis toolkit"));
+ assertThat(content, containsString("detects and extracts metadata and text"));
+
+ stream.close();
+ }
+
+ @Test
+ public void whenUsingFacade_thenContentIsReturned() throws IOException, TikaException {
+ InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.docx");
+ String content = TikaAnalysis.extractContentUsingFacade(stream);
+
+ assertThat(content, containsString("Apache Tika - a content analysis toolkit"));
+ assertThat(content, containsString("detects and extracts metadata and text"));
+
+ stream.close();
+ }
+
+ @Test
+ public void whenUsingParser_thenMetadataIsReturned() throws IOException, TikaException, SAXException {
+ InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.xlsx");
+ Metadata metadata = TikaAnalysis.extractMetadatatUsingParser(stream);
+
+ assertEquals("org.apache.tika.parser.DefaultParser", metadata.get("X-Parsed-By"));
+ assertEquals("Microsoft Office User", metadata.get("Author"));
+
+ stream.close();
+ }
+
+ @Test
+ public void whenUsingFacade_thenMetadataIsReturned() throws IOException, TikaException {
+ InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.xlsx");
+ Metadata metadata = TikaAnalysis.extractMetadatatUsingFacade(stream);
+
+ assertEquals("org.apache.tika.parser.DefaultParser", metadata.get("X-Parsed-By"));
+ assertEquals("Microsoft Office User", metadata.get("Author"));
+
+ stream.close();
+ }
+}
diff --git a/apache-tika/src/test/resources/tika.docx b/apache-tika/src/test/resources/tika.docx
new file mode 100644
index 0000000000..0a01ccef55
Binary files /dev/null and b/apache-tika/src/test/resources/tika.docx differ
diff --git a/apache-tika/src/test/resources/tika.txt b/apache-tika/src/test/resources/tika.txt
new file mode 100644
index 0000000000..26923836de
Binary files /dev/null and b/apache-tika/src/test/resources/tika.txt differ
diff --git a/apache-tika/src/test/resources/tika.xlsx b/apache-tika/src/test/resources/tika.xlsx
new file mode 100644
index 0000000000..110a0b2dd5
Binary files /dev/null and b/apache-tika/src/test/resources/tika.xlsx differ
diff --git a/apache-zookeeper/pom.xml b/apache-zookeeper/pom.xml
new file mode 100644
index 0000000000..3a6fc1787b
--- /dev/null
+++ b/apache-zookeeper/pom.xml
@@ -0,0 +1,36 @@
+
+ 4.0.0
+ com.baeldung
+ apache-zookeeper
+ 0.0.1-SNAPSHOT
+ jar
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.apache.zookeeper
+ zookeeper
+ 3.3.2
+
+
+ com.sun.jmx
+ jmxri
+
+
+ com.sun.jdmk
+ jmxtools
+
+
+ javax.jms
+ jms
+
+
+
+
+
diff --git a/apache-zookeeper/src/main/java/com/baeldung/zookeeper/connection/ZKConnection.java b/apache-zookeeper/src/main/java/com/baeldung/zookeeper/connection/ZKConnection.java
new file mode 100644
index 0000000000..0678250d57
--- /dev/null
+++ b/apache-zookeeper/src/main/java/com/baeldung/zookeeper/connection/ZKConnection.java
@@ -0,0 +1,33 @@
+package com.baeldung.zookeeper.connection;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.apache.zookeeper.ZooKeeper;
+
+public class ZKConnection {
+ private ZooKeeper zoo;
+ final CountDownLatch connectionLatch = new CountDownLatch(1);
+
+ public ZKConnection() {
+ }
+
+ public ZooKeeper connect(String host) throws IOException, InterruptedException {
+ zoo = new ZooKeeper(host, 2000, new Watcher() {
+ public void process(WatchedEvent we) {
+ if (we.getState() == KeeperState.SyncConnected) {
+ connectionLatch.countDown();
+ }
+ }
+ });
+ connectionLatch.await();
+ return zoo;
+ }
+
+ public void close() throws InterruptedException {
+ zoo.close();
+ }
+}
diff --git a/apache-zookeeper/src/main/java/com/baeldung/zookeeper/manager/ZKManager.java b/apache-zookeeper/src/main/java/com/baeldung/zookeeper/manager/ZKManager.java
new file mode 100644
index 0000000000..0c0ad52123
--- /dev/null
+++ b/apache-zookeeper/src/main/java/com/baeldung/zookeeper/manager/ZKManager.java
@@ -0,0 +1,35 @@
+package com.baeldung.zookeeper.manager;
+
+import org.apache.zookeeper.KeeperException;
+
+public interface ZKManager {
+ /**
+ * Create a Znode and save some data
+ *
+ * @param path
+ * @param data
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void create(String path, byte[] data) throws KeeperException, InterruptedException;
+
+ /**
+ * Get ZNode Data
+ *
+ * @param path
+ * @param boolean watchFlag
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public Object getZNodeData(String path, boolean watchFlag);
+
+ /**
+ * Update the ZNode Data
+ *
+ * @param path
+ * @param data
+ * @throws KeeperException
+ * @throws InterruptedException
+ */
+ public void update(String path, byte[] data) throws KeeperException, InterruptedException, KeeperException;
+}
diff --git a/apache-zookeeper/src/main/java/com/baeldung/zookeeper/manager/ZKManagerImpl.java b/apache-zookeeper/src/main/java/com/baeldung/zookeeper/manager/ZKManagerImpl.java
new file mode 100644
index 0000000000..adf76bc0f2
--- /dev/null
+++ b/apache-zookeeper/src/main/java/com/baeldung/zookeeper/manager/ZKManagerImpl.java
@@ -0,0 +1,58 @@
+package com.baeldung.zookeeper.manager;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+
+import com.baeldung.zookeeper.connection.ZKConnection;
+
+public class ZKManagerImpl implements ZKManager {
+ private static ZooKeeper zkeeper;
+ private static ZKConnection zkConnection;
+
+ public ZKManagerImpl() {
+ initialize();
+ }
+
+ /** * Initialize connection */
+ private void initialize() {
+ try {
+ zkConnection = new ZKConnection();
+ zkeeper = zkConnection.connect("localhost");
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ public void closeConnection() {
+ try {
+ zkConnection.close();
+ } catch (InterruptedException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ public void create(String path, byte[] data) throws KeeperException, InterruptedException {
+ zkeeper.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+ }
+
+ public Object getZNodeData(String path, boolean watchFlag) {
+ try {
+ byte[] b = null;
+ b = zkeeper.getData(path, null, null);
+ String data = new String(b, "UTF-8");
+ System.out.println(data);
+ return data;
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ return null;
+ }
+
+ public void update(String path, byte[] data) throws KeeperException, InterruptedException {
+ int version = zkeeper.exists(path, true)
+ .getVersion();
+ zkeeper.setData(path, data, version);
+ }
+}
diff --git a/aws/src/main/java/com/baeldung/ec2/EC2Application.java b/aws/src/main/java/com/baeldung/ec2/EC2Application.java
new file mode 100644
index 0000000000..6755188fcd
--- /dev/null
+++ b/aws/src/main/java/com/baeldung/ec2/EC2Application.java
@@ -0,0 +1,137 @@
+package com.baeldung.ec2;
+
+import java.util.Arrays;
+
+import com.amazonaws.auth.AWSCredentials;
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.regions.Regions;
+import com.amazonaws.services.ec2.AmazonEC2;
+import com.amazonaws.services.ec2.AmazonEC2ClientBuilder;
+import com.amazonaws.services.ec2.model.AuthorizeSecurityGroupIngressRequest;
+import com.amazonaws.services.ec2.model.CreateKeyPairRequest;
+import com.amazonaws.services.ec2.model.CreateKeyPairResult;
+import com.amazonaws.services.ec2.model.CreateSecurityGroupRequest;
+import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
+import com.amazonaws.services.ec2.model.DescribeInstancesResult;
+import com.amazonaws.services.ec2.model.DescribeKeyPairsRequest;
+import com.amazonaws.services.ec2.model.DescribeKeyPairsResult;
+import com.amazonaws.services.ec2.model.IpPermission;
+import com.amazonaws.services.ec2.model.IpRange;
+import com.amazonaws.services.ec2.model.MonitorInstancesRequest;
+import com.amazonaws.services.ec2.model.RebootInstancesRequest;
+import com.amazonaws.services.ec2.model.RunInstancesRequest;
+import com.amazonaws.services.ec2.model.StartInstancesRequest;
+import com.amazonaws.services.ec2.model.StopInstancesRequest;
+import com.amazonaws.services.ec2.model.UnmonitorInstancesRequest;
+
+public class EC2Application {
+
+ private static final AWSCredentials credentials;
+
+ static {
+ // put your accesskey and secretkey here
+ credentials = new BasicAWSCredentials(
+ "",
+ ""
+ );
+ }
+
+ public static void main(String[] args) {
+
+ // Set up the client
+ AmazonEC2 ec2Client = AmazonEC2ClientBuilder.standard()
+ .withCredentials(new AWSStaticCredentialsProvider(credentials))
+ .withRegion(Regions.US_EAST_1)
+ .build();
+
+ // Create a security group
+ CreateSecurityGroupRequest createSecurityGroupRequest = new CreateSecurityGroupRequest().withGroupName("BaeldungSecurityGroup")
+ .withDescription("Baeldung Security Group");
+ ec2Client.createSecurityGroup(createSecurityGroupRequest);
+
+ // Allow HTTP and SSH traffic
+ IpRange ipRange1 = new IpRange().withCidrIp("0.0.0.0/0");
+
+ IpPermission ipPermission1 = new IpPermission().withIpv4Ranges(Arrays.asList(new IpRange[] { ipRange1 }))
+ .withIpProtocol("tcp")
+ .withFromPort(80)
+ .withToPort(80);
+
+ IpPermission ipPermission2 = new IpPermission().withIpv4Ranges(Arrays.asList(new IpRange[] { ipRange1 }))
+ .withIpProtocol("tcp")
+ .withFromPort(22)
+ .withToPort(22);
+
+ AuthorizeSecurityGroupIngressRequest authorizeSecurityGroupIngressRequest = new AuthorizeSecurityGroupIngressRequest()
+ .withGroupName("BaeldungSecurityGroup")
+ .withIpPermissions(ipPermission1, ipPermission2);
+
+ ec2Client.authorizeSecurityGroupIngress(authorizeSecurityGroupIngressRequest);
+
+ // Create KeyPair
+ CreateKeyPairRequest createKeyPairRequest = new CreateKeyPairRequest()
+ .withKeyName("baeldung-key-pair");
+ CreateKeyPairResult createKeyPairResult = ec2Client.createKeyPair(createKeyPairRequest);
+ String privateKey = createKeyPairResult
+ .getKeyPair()
+ .getKeyMaterial(); // make sure you keep it, the private key, Amazon doesn't store the private key
+
+ // See what key-pairs you've got
+ DescribeKeyPairsRequest describeKeyPairsRequest = new DescribeKeyPairsRequest();
+ DescribeKeyPairsResult describeKeyPairsResult = ec2Client.describeKeyPairs(describeKeyPairsRequest);
+
+ // Launch an Amazon Instance
+ RunInstancesRequest runInstancesRequest = new RunInstancesRequest().withImageId("ami-97785bed") // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/usingsharedamis-finding.html
+ .withInstanceType("t2.micro") // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html
+ .withMinCount(1)
+ .withMaxCount(1)
+ .withKeyName("baeldung-key-pair") // optional - if not present, can't connect to instance
+ .withSecurityGroups("BaeldungSecurityGroup");
+
+ String yourInstanceId = ec2Client.runInstances(runInstancesRequest).getReservation().getInstances().get(0).getInstanceId();
+
+ // Start an Instance
+ StartInstancesRequest startInstancesRequest = new StartInstancesRequest()
+ .withInstanceIds(yourInstanceId);
+
+ ec2Client.startInstances(startInstancesRequest);
+
+ // Monitor Instances
+ MonitorInstancesRequest monitorInstancesRequest = new MonitorInstancesRequest()
+ .withInstanceIds(yourInstanceId);
+
+ ec2Client.monitorInstances(monitorInstancesRequest);
+
+ UnmonitorInstancesRequest unmonitorInstancesRequest = new UnmonitorInstancesRequest()
+ .withInstanceIds(yourInstanceId);
+
+ ec2Client.unmonitorInstances(unmonitorInstancesRequest);
+
+ // Reboot an Instance
+
+ RebootInstancesRequest rebootInstancesRequest = new RebootInstancesRequest()
+ .withInstanceIds(yourInstanceId);
+
+ ec2Client.rebootInstances(rebootInstancesRequest);
+
+ // Stop an Instance
+ StopInstancesRequest stopInstancesRequest = new StopInstancesRequest()
+ .withInstanceIds(yourInstanceId);
+
+ ec2Client.stopInstances(stopInstancesRequest)
+ .getStoppingInstances()
+ .get(0)
+ .getPreviousState()
+ .getName();
+
+ // Describe an Instance
+ DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest();
+ DescribeInstancesResult response = ec2Client.describeInstances(describeInstancesRequest);
+ System.out.println(response.getReservations()
+ .get(0)
+ .getInstances()
+ .get(0)
+ .getKernelId());
+ }
+}
diff --git a/bootique/dependency-reduced-pom.xml b/bootique/dependency-reduced-pom.xml
index ed18f4e42a..ab09cfb7b1 100644
--- a/bootique/dependency-reduced-pom.xml
+++ b/bootique/dependency-reduced-pom.xml
@@ -28,8 +28,14 @@
junit
junit
- 3.8.1
+ 4.12
test
+
+
+ hamcrest-core
+ org.hamcrest
+
+
diff --git a/camel-api/pom.xml b/camel-api/pom.xml
index 6db9f9bfd1..c342a73150 100644
--- a/camel-api/pom.xml
+++ b/camel-api/pom.xml
@@ -12,7 +12,7 @@
UTF-8
- 3.6.0
+ 3.7.0
2.19.1
2.19.1
1.5.4.RELEASE
diff --git a/cas/cas-secured-app/README.md b/cas/cas-secured-app/README.md
new file mode 100644
index 0000000000..01c5f91988
--- /dev/null
+++ b/cas/cas-secured-app/README.md
@@ -0,0 +1,2 @@
+## Relevant articles:
+- [CAS SSO With Spring Security](http://www.baeldung.com/spring-security-cas-sso)
diff --git a/cas/cas-secured-app/pom.xml b/cas/cas-secured-app/pom.xml
index f66d54ae67..d52597412e 100644
--- a/cas/cas-secured-app/pom.xml
+++ b/cas/cas-secured-app/pom.xml
@@ -14,7 +14,7 @@
org.springframework.boot
spring-boot-starter-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.M7
@@ -65,18 +65,28 @@
org.springframework.boot
spring-boot-maven-plugin
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+ 3
+ true
+
+ **/*IntegrationTest.java
+ **/*LongRunningUnitTest.java
+ **/*ManualTest.java
+ **/JdbcTest.java
+ **/*LiveTest.java
+
+
+
+
+