Merge branch 'masterupstream' into tutorials/jerseyFiltersInterceptors
This commit is contained in:
commit
411f4e9b97
|
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* ({@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()}))
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @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 + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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: <br>
|
||||||
|
* <br>
|
||||||
|
* 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? <br>
|
||||||
|
* <br>
|
||||||
|
*
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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: <br>
|
||||||
|
* <br>
|
||||||
|
* 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? <br>
|
||||||
|
* <br>
|
||||||
|
* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>apache-zookeeper</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.sun.jmx</groupId>
|
||||||
|
<artifactId>jmxri</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.sun.jdmk</groupId>
|
||||||
|
<artifactId>jmxtools</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>javax.jms</groupId>
|
||||||
|
<artifactId>jms</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>checker-plugin</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>checker-plugin</name>
|
||||||
|
<url>http://maven.apache.org</url>
|
||||||
|
|
||||||
|
<!-- https://checkerframework.org/manual/#maven -->
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- These properties will be set by the Maven Dependency plugin -->
|
||||||
|
<annotatedJdk>${org.checkerframework:jdk8:jar}</annotatedJdk>
|
||||||
|
<!-- Uncomment to use the Type Annotations compiler. -->
|
||||||
|
<!--
|
||||||
|
<typeAnnotationsJavac>${org.checkerframework:compiler:jar}</typeAnnotationsJavac>
|
||||||
|
-->
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Annotations from the Checker Framework: nullness, interning, locking, ... -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
<artifactId>checker-qual</artifactId>
|
||||||
|
<version>2.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
<artifactId>checker</artifactId>
|
||||||
|
<version>2.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
<artifactId>jdk8</artifactId>
|
||||||
|
<version>2.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- The Type Annotations compiler. Uncomment if using annotations in comments. -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.checkerframework</groupId>
|
||||||
|
<artifactId>compiler</artifactId>
|
||||||
|
<version>2.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<!-- This plugin will set properties values using dependency information -->
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<!--
|
||||||
|
Goal that sets a property pointing to the artifact file for each project dependency.
|
||||||
|
For each dependency (direct and transitive) a project property will be set which
|
||||||
|
follows the:
|
||||||
|
|
||||||
|
groupId:artifactId:type:[classifier]
|
||||||
|
|
||||||
|
form and contains the path to the resolved artifact. -->
|
||||||
|
<goal>properties</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.6.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<!-- Uncomment the following line to use the type annotations compiler. -->
|
||||||
|
<!-- <fork>true</fork> -->
|
||||||
|
<compilerArguments>
|
||||||
|
<Xmaxerrs>10000</Xmaxerrs>
|
||||||
|
<Xmaxwarns>10000</Xmaxwarns>
|
||||||
|
</compilerArguments>
|
||||||
|
<annotationProcessors>
|
||||||
|
<!-- Add all the checkers you want to enable here -->
|
||||||
|
<annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
|
||||||
|
<annotationProcessor>org.checkerframework.checker.interning.InterningChecker</annotationProcessor>
|
||||||
|
<annotationProcessor>org.checkerframework.checker.fenum.FenumChecker</annotationProcessor>
|
||||||
|
<annotationProcessor>org.checkerframework.checker.formatter.FormatterChecker</annotationProcessor>
|
||||||
|
<annotationProcessor>org.checkerframework.checker.regex.RegexChecker</annotationProcessor>
|
||||||
|
</annotationProcessors>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-AprintErrorStack</arg>
|
||||||
|
|
||||||
|
<!-- location of the annotated JDK, which comes from a Maven dependency -->
|
||||||
|
<arg>-Xbootclasspath/p:${annotatedJdk}</arg>
|
||||||
|
<!--
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Uncomment the following line to use the type annotations compiler. -->
|
||||||
|
<!--
|
||||||
|
<arg>-J-Xbootclasspath/p:${typeAnnotationsJavac}</arg>
|
||||||
|
-->
|
||||||
|
<!-- Uncomment the following line to turn type-checking warnings into errors. -->
|
||||||
|
<arg>-Awarns</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<String, String> 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) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Groovy
|
||||||
|
|
||||||
|
## Relevant articles:
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>core-groovy</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<url>http://jcenter.bintray.com</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy</artifactId>
|
||||||
|
<version>2.4.13</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy-sql</artifactId>
|
||||||
|
<version>2.4.13</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-runner</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hsqldb</groupId>
|
||||||
|
<artifactId>hsqldb</artifactId>
|
||||||
|
<version>2.4.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmavenplus</groupId>
|
||||||
|
<artifactId>gmavenplus-plugin</artifactId>
|
||||||
|
<version>1.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>addSources</goal>
|
||||||
|
<goal>addTestSources</goal>
|
||||||
|
<goal>compile</goal>
|
||||||
|
<goal>compileTests</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<version>2.19.1</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>junit5</id>
|
||||||
|
<goals>
|
||||||
|
<goal>integration-test</goal>
|
||||||
|
<goal>verify</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<includes>
|
||||||
|
<include>**/*Test5.java</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<kotlin-maven-plugin.version>1.1.2</kotlin-maven-plugin.version>
|
||||||
|
<kotlin-test-junit.version>1.1.2</kotlin-test-junit.version>
|
||||||
|
<kotlin-stdlib.version>1.1.2</kotlin-stdlib.version>
|
||||||
|
<kotlin-reflect.version>1.1.2</kotlin-reflect.version>
|
||||||
|
<kotlinx.version>0.15</kotlinx.version>
|
||||||
|
<mockito-kotlin.version>1.5.0</mockito-kotlin.version>
|
||||||
|
|
||||||
|
<junit.jupiter.version>5.0.0</junit.jupiter.version>
|
||||||
|
<junit.platform.version>1.0.0</junit.platform.version>
|
||||||
|
<junit.vintage.version>4.12.0</junit.vintage.version>
|
||||||
|
<junit4.version>4.12</junit4.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -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 '))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
|
@ -40,3 +40,4 @@
|
||||||
- [Efficient Word Frequency Calculator in Java](http://www.baeldung.com/java-word-frequency)
|
- [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)
|
- [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)
|
- [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)
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class ShufflingCollectionsUnitTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenShufflingMapKeys_thenValuesAreShuffled() {
|
public void whenShufflingMapEntries_thenValuesAreShuffled() {
|
||||||
Map<Integer, String> studentsById = new HashMap<>();
|
Map<Integer, String> studentsById = new HashMap<>();
|
||||||
studentsById.put(1, "Foo");
|
studentsById.put(1, "Foo");
|
||||||
studentsById.put(2, "Bar");
|
studentsById.put(2, "Bar");
|
||||||
|
@ -32,11 +32,11 @@ public class ShufflingCollectionsUnitTest {
|
||||||
System.out.println("Students before shuffling:");
|
System.out.println("Students before shuffling:");
|
||||||
System.out.println(studentsById.values());
|
System.out.println(studentsById.values());
|
||||||
|
|
||||||
List<Integer> shuffledStudentIds = new ArrayList<>(studentsById.keySet());
|
List<Map.Entry<Integer, String>> shuffledStudentEntries = new ArrayList<>(studentsById.entrySet());
|
||||||
Collections.shuffle(shuffledStudentIds);
|
Collections.shuffle(shuffledStudentEntries);
|
||||||
|
|
||||||
List<String> shuffledStudents = shuffledStudentIds.stream()
|
List<String> shuffledStudents = shuffledStudentEntries.stream()
|
||||||
.map(id -> studentsById.get(id))
|
.map(Map.Entry::getValue)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
System.out.println("Students after shuffling");
|
System.out.println("Students after shuffling");
|
||||||
|
|
|
@ -10,7 +10,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import com.jayway.awaitility.Awaitility;
|
import com.jayway.awaitility.Awaitility;
|
||||||
|
|
||||||
public class StopThreadTest {
|
public class StopThreadManualTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenStoppedThreadIsStopped() throws InterruptedException {
|
public void whenStoppedThreadIsStopped() throws InterruptedException {
|
|
@ -127,3 +127,4 @@
|
||||||
- [Polymorphism in Java](http://www.baeldung.com/java-polymorphism)
|
- [Polymorphism in Java](http://www.baeldung.com/java-polymorphism)
|
||||||
- [Recursion In Java](http://www.baeldung.com/java-recursion)
|
- [Recursion In Java](http://www.baeldung.com/java-recursion)
|
||||||
- [A Guide to the finalize Method in Java](http://www.baeldung.com/java-finalize)
|
- [A Guide to the finalize Method in Java](http://www.baeldung.com/java-finalize)
|
||||||
|
- [Compiling Java *.class Files with javac](http://www.baeldung.com/javac)
|
||||||
|
|
|
@ -78,6 +78,11 @@
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>${jackson.version}</version>
|
<version>${jackson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>${gson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- logging -->
|
<!-- logging -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -468,6 +473,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<!-- marshalling -->
|
<!-- marshalling -->
|
||||||
<jackson.version>2.8.5</jackson.version>
|
<jackson.version>2.8.5</jackson.version>
|
||||||
|
<gson.version>2.8.2</gson.version>
|
||||||
|
|
||||||
<!-- logging -->
|
<!-- logging -->
|
||||||
<org.slf4j.version>1.7.21</org.slf4j.version>
|
<org.slf4j.version>1.7.21</org.slf4j.version>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.classloader;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class CustomClassLoader extends ClassLoader {
|
||||||
|
|
||||||
|
|
||||||
|
public Class getClass(String name) throws ClassNotFoundException {
|
||||||
|
byte[] b = loadClassFromFile(name);
|
||||||
|
return defineClass(name, b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] loadClassFromFile(String fileName) {
|
||||||
|
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
|
||||||
|
fileName.replace('.', File.separatorChar) + ".class");
|
||||||
|
byte[] buffer;
|
||||||
|
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||||
|
int nextValue = 0;
|
||||||
|
try {
|
||||||
|
while ( (nextValue = inputStream.read()) != -1 ) {
|
||||||
|
byteStream.write(nextValue);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
buffer = byteStream.toByteArray();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.baeldung.classloader;
|
||||||
|
|
||||||
|
import com.sun.javafx.util.Logging;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class PrintClassLoader {
|
||||||
|
|
||||||
|
public void printClassLoaders() throws ClassNotFoundException {
|
||||||
|
|
||||||
|
System.out.println("Classloader of this class:" + PrintClassLoader.class.getClassLoader());
|
||||||
|
System.out.println("Classloader of Logging:" + Logging.class.getClassLoader());
|
||||||
|
System.out.println("Classloader of ArrayList:" + ArrayList.class.getClassLoader());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Address implements Serializable, Cloneable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
try {
|
||||||
|
return (Address) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
return new Address(this.street, this.getCity(), this.getCountry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1740913841244949416L;
|
||||||
|
private String street;
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
public Address(Address that) {
|
||||||
|
this(that.getStreet(), that.getCity(), that.getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String street, String city, String country) {
|
||||||
|
this.street = street;
|
||||||
|
this.city = city;
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreet(String street) {
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(String city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class User implements Serializable, Cloneable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3427002229954777557L;
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
private Address address;
|
||||||
|
|
||||||
|
public User(String firstName, String lastName, Address address) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(User that) {
|
||||||
|
this(that.getFirstName(), that.getLastName(), new Address(that.getAddress()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
User user;
|
||||||
|
try {
|
||||||
|
user = (User) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
user = new User(this.getFirstName(), this.getLastName(), this.getAddress());
|
||||||
|
}
|
||||||
|
user.address = (Address) this.address.clone();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.baeldung.designpatterns.flyweight;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a car. This class is immutable.
|
||||||
|
*
|
||||||
|
* @author Donato Rimenti
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
|
public class Car implements Vehicle {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger.
|
||||||
|
*/
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(Car.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The car's engine.
|
||||||
|
*/
|
||||||
|
private Engine engine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The car's color.
|
||||||
|
*/
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Car.
|
||||||
|
*
|
||||||
|
* @param engine
|
||||||
|
* the {@link #engine}
|
||||||
|
* @param color
|
||||||
|
* the {@link #color}
|
||||||
|
*/
|
||||||
|
public Car(Engine engine, Color color) {
|
||||||
|
this.engine = engine;
|
||||||
|
this.color = color;
|
||||||
|
|
||||||
|
// Building a new car is a very expensive operation!
|
||||||
|
try {
|
||||||
|
Thread.sleep(2000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOG.error("Error while creating a new car", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see com.baeldung.designpatterns.flyweight.Vehicle#start()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
LOG.info("Car is starting!");
|
||||||
|
engine.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see com.baeldung.designpatterns.flyweight.Vehicle#stop()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
LOG.info("Car is stopping!");
|
||||||
|
engine.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see com.baeldung.designpatterns.flyweight.Vehicle#getColor()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Color getColor() {
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.designpatterns.flyweight;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Engine for a vehicle.
|
||||||
|
*
|
||||||
|
* @author Donato Rimenti
|
||||||
|
*/
|
||||||
|
public class Engine {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger.
|
||||||
|
*/
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(Engine.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the engine.
|
||||||
|
*/
|
||||||
|
public void start() {
|
||||||
|
LOG.info("Engine is starting!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the engine.
|
||||||
|
*/
|
||||||
|
public void stop() {
|
||||||
|
LOG.info("Engine is stopping!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.designpatterns.flyweight;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for a vehicle.
|
||||||
|
*
|
||||||
|
* @author Donato Rimenti
|
||||||
|
*/
|
||||||
|
public interface Vehicle {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the vehicle.
|
||||||
|
*/
|
||||||
|
public void start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the vehicle.
|
||||||
|
*/
|
||||||
|
public void stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the color of the vehicle.
|
||||||
|
*
|
||||||
|
* @return the color of the vehicle
|
||||||
|
*/
|
||||||
|
public Color getColor();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.baeldung.designpatterns.flyweight;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory which implements the Flyweight pattern to return an existing vehicle
|
||||||
|
* if present or a new one otherwise.
|
||||||
|
*
|
||||||
|
* @author Donato Rimenti
|
||||||
|
*/
|
||||||
|
public class VehicleFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the already created vehicles.
|
||||||
|
*/
|
||||||
|
private static Map<Color, Vehicle> vehiclesCache = new HashMap<Color, Vehicle>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent this class instantiation.
|
||||||
|
*/
|
||||||
|
private VehicleFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a vehicle of the same color passed as argument. If that vehicle
|
||||||
|
* was already created by this factory, that vehicle is returned, otherwise
|
||||||
|
* a new one is created and returned.
|
||||||
|
*
|
||||||
|
* @param color
|
||||||
|
* the color of the vehicle to return
|
||||||
|
* @return a vehicle of the specified color
|
||||||
|
*/
|
||||||
|
public static Vehicle createVehicle(Color color) {
|
||||||
|
// Looks for the requested vehicle into the cache.
|
||||||
|
// If the vehicle doesn't exist, a new one is created.
|
||||||
|
Vehicle newVehicle = vehiclesCache.computeIfAbsent(color, newColor -> {
|
||||||
|
// Creates the new car.
|
||||||
|
Engine newEngine = new Engine();
|
||||||
|
return new Car(newEngine, newColor);
|
||||||
|
});
|
||||||
|
return newVehicle;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public class ArmoredCar extends Car implements Floatable, Flyable{
|
||||||
|
private int bulletProofWindows;
|
||||||
|
private String model;
|
||||||
|
|
||||||
|
public void remoteStartCar() {
|
||||||
|
// this vehicle can be started by using a remote control
|
||||||
|
}
|
||||||
|
|
||||||
|
public String registerModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAValue() {
|
||||||
|
return super.model; // returns value of model defined in base class Car
|
||||||
|
// return this.model; // will return value of model defined in ArmoredCar
|
||||||
|
// return model; // will return value of model defined in ArmoredCar
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String msg() {
|
||||||
|
// return super.msg(); // this won't compile.
|
||||||
|
return "ArmoredCar";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void floatOnWater() {
|
||||||
|
System.out.println("I can float!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fly() {
|
||||||
|
System.out.println("I can fly!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void aMethod() {
|
||||||
|
// System.out.println(duration); // Won't compile
|
||||||
|
System.out.println(Floatable.duration); // outputs 10
|
||||||
|
System.out.println(Flyable.duration); // outputs 20
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public class BMW extends Car {
|
||||||
|
public BMW() {
|
||||||
|
super(5, "BMW");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public class Car {
|
||||||
|
private final int DEFAULT_WHEEL_COUNT = 5;
|
||||||
|
private final String DEFAULT_MODEL = "Basic";
|
||||||
|
|
||||||
|
protected int wheels;
|
||||||
|
protected String model;
|
||||||
|
|
||||||
|
public Car() {
|
||||||
|
this.wheels = DEFAULT_WHEEL_COUNT;
|
||||||
|
this.model = DEFAULT_MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Car(int wheels, String model) {
|
||||||
|
this.wheels = wheels;
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
// Check essential parts
|
||||||
|
// If okay, start.
|
||||||
|
}
|
||||||
|
public static int count = 10;
|
||||||
|
public static String msg() {
|
||||||
|
return "Car";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public class Employee {
|
||||||
|
private String name;
|
||||||
|
private Car car;
|
||||||
|
|
||||||
|
public Employee(String name, Car car) {
|
||||||
|
this.name = name;
|
||||||
|
this.car = car;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Car getCar() {
|
||||||
|
return car;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public interface Floatable {
|
||||||
|
int duration = 10;
|
||||||
|
void floatOnWater();
|
||||||
|
|
||||||
|
default void repair() {
|
||||||
|
System.out.println("Repairing Floatable object");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public interface Flyable {
|
||||||
|
int duration = 10;
|
||||||
|
void fly();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commented
|
||||||
|
*/
|
||||||
|
//default void repair() {
|
||||||
|
// System.out.println("Repairing Flyable object");
|
||||||
|
//}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public class SpaceCar extends Car implements SpaceTraveller {
|
||||||
|
@Override
|
||||||
|
public void floatOnWater() {
|
||||||
|
System.out.println("SpaceCar floating!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fly() {
|
||||||
|
System.out.println("SpaceCar flying!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteControl() {
|
||||||
|
System.out.println("SpaceCar being controlled remotely!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
public interface SpaceTraveller extends Floatable, Flyable {
|
||||||
|
int duration = 10;
|
||||||
|
void remoteControl();
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.recursion;
|
||||||
|
|
||||||
|
public class BinaryNode {
|
||||||
|
int value;
|
||||||
|
BinaryNode left;
|
||||||
|
BinaryNode right;
|
||||||
|
|
||||||
|
public BinaryNode(int value){
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
public void setValue(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
public BinaryNode getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
public void setLeft(BinaryNode left) {
|
||||||
|
this.left = left;
|
||||||
|
}
|
||||||
|
public BinaryNode getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
public void setRight(BinaryNode right) {
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package com.baeldung.recursion;
|
||||||
|
|
||||||
|
public class RecursionExample {
|
||||||
|
|
||||||
|
public int sum(int n){
|
||||||
|
if (n >= 1){
|
||||||
|
return sum(n - 1) + n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int tailSum(int currentSum, int n){
|
||||||
|
if (n <= 1) {
|
||||||
|
return currentSum + n;
|
||||||
|
}
|
||||||
|
return tailSum(currentSum + n, n - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int iterativeSum(int n){
|
||||||
|
int sum = 0;
|
||||||
|
if(n < 0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for(int i=0; i<=n; i++){
|
||||||
|
sum += i;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int powerOf10(int n){
|
||||||
|
if (n == 0){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return powerOf10(n-1)*10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int fibonacci(int n){
|
||||||
|
if (n <=1 ){
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return fibonacci(n-1) + fibonacci(n-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toBinary(int n){
|
||||||
|
if (n <= 1 ){
|
||||||
|
return String.valueOf(n);
|
||||||
|
}
|
||||||
|
return toBinary(n / 2) + String.valueOf(n % 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int calculateTreeHeight(BinaryNode root){
|
||||||
|
if (root!= null){
|
||||||
|
if (root.getLeft() != null || root.getRight() != null){
|
||||||
|
return 1 + max(calculateTreeHeight(root.left) , calculateTreeHeight(root.right));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int max(int a,int b){
|
||||||
|
return a>b ? a:b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.resourcebundle;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class ExampleControl extends ResourceBundle.Control {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Locale> getCandidateLocales(String s, Locale locale) {
|
||||||
|
return Arrays.asList(new Locale("pl", "PL"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.resourcebundle;
|
||||||
|
|
||||||
|
import java.util.ListResourceBundle;
|
||||||
|
|
||||||
|
public class ExampleResource extends ListResourceBundle {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object[][] getContents() {
|
||||||
|
return new Object[][] {
|
||||||
|
{ "greeting", "hello" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.resourcebundle;
|
||||||
|
|
||||||
|
import java.util.ListResourceBundle;
|
||||||
|
|
||||||
|
public class ExampleResource_pl extends ListResourceBundle {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object[][] getContents() {
|
||||||
|
return new Object[][] {
|
||||||
|
{ "greeting", "cześć" },
|
||||||
|
{ "language", "polish" },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.baeldung.resourcebundle;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ListResourceBundle;
|
||||||
|
|
||||||
|
public class ExampleResource_pl_PL extends ListResourceBundle {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object[][] getContents() {
|
||||||
|
return new Object[][] {
|
||||||
|
{ "currency", "polish zloty" },
|
||||||
|
{ "toUsdRate", new BigDecimal("3.401") },
|
||||||
|
{ "cities", new String[] { "Warsaw", "Cracow" } }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Buttons
|
||||||
|
cancelButton=cancel
|
||||||
|
continueButton continue
|
||||||
|
|
||||||
|
! Labels
|
||||||
|
helloLabel:hello
|
|
@ -0,0 +1 @@
|
||||||
|
deleteButton=delete
|
|
@ -0,0 +1,3 @@
|
||||||
|
backButton=cofnij
|
||||||
|
helloLabel=cze\u015b\u0107
|
||||||
|
helloLabelNoEncoding=cześć
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.classloader;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class CustomClassLoaderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void customLoader() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
|
||||||
|
|
||||||
|
CustomClassLoader customClassLoader = new CustomClassLoader();
|
||||||
|
Class<?> c = customClassLoader.getClass(PrintClassLoader.class.getName());
|
||||||
|
|
||||||
|
Object ob = c.newInstance();
|
||||||
|
|
||||||
|
Method md = c.getMethod("printClassLoaders");
|
||||||
|
md.invoke(ob);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.classloader;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PrintClassLoaderTest {
|
||||||
|
@Test(expected = ClassNotFoundException.class)
|
||||||
|
public void givenAppClassLoader_whenParentClassLoader_thenClassNotFoundException() throws Exception {
|
||||||
|
PrintClassLoader sampleClassLoader = (PrintClassLoader) Class.forName(PrintClassLoader.class.getName()).newInstance();
|
||||||
|
sampleClassLoader.printClassLoaders();
|
||||||
|
Class.forName(PrintClassLoader.class.getName(), true, PrintClassLoader.class.getClassLoader().getParent());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.SerializationUtils;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
public class DeepCopyUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCreatingDeepCopyWithCopyConstructor_thenObjectsShouldNotBeSame() {
|
||||||
|
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
|
||||||
|
User deepCopy = new User(pm);
|
||||||
|
|
||||||
|
assertThat(deepCopy).isNotSameAs(pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenConstructorCopyShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User deepCopy = new User(pm);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenCloneCopyShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User deepCopy = (User) pm.clone();
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenCommonsCloneShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User deepCopy = (User) SerializationUtils.clone(pm);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenGsonCloneShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
Gson gson = new Gson();
|
||||||
|
User deepCopy = gson.fromJson(gson.toJson(pm), User.class);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenJacksonCopyShouldNotChange() throws IOException {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
User deepCopy = objectMapper.readValue(objectMapper.writeValueAsString(pm), User.class);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void whenMakingCopies_thenShowHowLongEachMethodTakes() throws CloneNotSupportedException, IOException {
|
||||||
|
int times = 1000000;
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = (User) SerializationUtils.clone(pm);
|
||||||
|
}
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Apache Commons Lang took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
Gson gson = new Gson();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = gson.fromJson(gson.toJson(pm), User.class);
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Gson took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = new User(pm);
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with the copy constructor took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = (User) pm.clone();
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Cloneable interface took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = objectMapper.readValue(objectMapper.writeValueAsString(pm), User.class);
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Jackson took " + (end - start) + " milliseconds.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ShallowCopyUnitTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenShallowCopying_thenObjectsShouldNotBeSame() {
|
||||||
|
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
|
||||||
|
User shallowCopy = new User(pm.getFirstName(), pm.getLastName(), pm.getAddress());
|
||||||
|
|
||||||
|
assertThat(shallowCopy)
|
||||||
|
.isNotSameAs(pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenCopyShouldChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User shallowCopy = new User(pm.getFirstName(), pm.getLastName(), pm.getAddress());
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(shallowCopy.getAddress().getCountry())
|
||||||
|
.isEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.designpatterns.flyweight;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for {@link VehicleFactory}.
|
||||||
|
*
|
||||||
|
* @author Donato Rimenti
|
||||||
|
*/
|
||||||
|
public class FlyweightUnitTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that when the {@link VehicleFactory} is asked to provide two
|
||||||
|
* vehicles of different colors, the objects returned are different.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void givenDifferentFlyweightObjects_whenEquals_thenFalse() {
|
||||||
|
Vehicle blackVehicle = VehicleFactory.createVehicle(Color.BLACK);
|
||||||
|
Vehicle blueVehicle = VehicleFactory.createVehicle(Color.BLUE);
|
||||||
|
|
||||||
|
Assert.assertNotNull("Object returned by the factory is null!", blackVehicle);
|
||||||
|
Assert.assertNotNull("Object returned by the factory is null!", blueVehicle);
|
||||||
|
Assert.assertNotEquals("Objects returned by the factory are equals!", blackVehicle, blueVehicle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that when the {@link VehicleFactory} is asked to provide two
|
||||||
|
* vehicles of the same colors, the same object is returned twice.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void givenSameFlyweightObjects_whenEquals_thenTrue() {
|
||||||
|
Vehicle blackVehicle = VehicleFactory.createVehicle(Color.BLACK);
|
||||||
|
Vehicle anotherBlackVehicle = VehicleFactory.createVehicle(Color.BLACK);
|
||||||
|
|
||||||
|
Assert.assertNotNull("Object returned by the factory is null!", blackVehicle);
|
||||||
|
Assert.assertNotNull("Object returned by the factory is null!", anotherBlackVehicle);
|
||||||
|
Assert.assertEquals("Objects returned by the factory are not equals!", blackVehicle, anotherBlackVehicle);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.baeldung.inheritance;
|
||||||
|
|
||||||
|
import com.baeldung.inheritance.*;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
public class AppTest extends TestCase {
|
||||||
|
|
||||||
|
public AppTest(String testName) {
|
||||||
|
super( testName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return new TestSuite(AppTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-access")
|
||||||
|
public void testStaticMethodUsingBaseClassVariable() {
|
||||||
|
Car first = new ArmoredCar();
|
||||||
|
assertEquals("Car", first.msg());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-access")
|
||||||
|
public void testStaticMethodUsingDerivedClassVariable() {
|
||||||
|
ArmoredCar second = new ArmoredCar();
|
||||||
|
assertEquals("ArmoredCar", second.msg());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAssignArmoredCarToCar() {
|
||||||
|
Employee e1 = new Employee("Shreya", new ArmoredCar());
|
||||||
|
assertNotNull(e1.getCar());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAssignSpaceCarToCar() {
|
||||||
|
Employee e2 = new Employee("Paul", new SpaceCar());
|
||||||
|
assertNotNull(e2.getCar());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBMWToCar() {
|
||||||
|
Employee e3 = new Employee("Pavni", new BMW());
|
||||||
|
assertNotNull(e3.getCar());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.baeldung.recursion;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class RecursionExampleTest {
|
||||||
|
|
||||||
|
RecursionExample recursion = new RecursionExample();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPowerOf10() {
|
||||||
|
int p0 = recursion.powerOf10(0);
|
||||||
|
int p1 = recursion.powerOf10(1);
|
||||||
|
int p4 = recursion.powerOf10(4);
|
||||||
|
|
||||||
|
Assert.assertEquals(1, p0);
|
||||||
|
Assert.assertEquals(10, p1);
|
||||||
|
Assert.assertEquals(10000, p4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFibonacci() {
|
||||||
|
int n0 = recursion.fibonacci(0);
|
||||||
|
int n1 = recursion.fibonacci(1);
|
||||||
|
int n7 = recursion.fibonacci(7);
|
||||||
|
|
||||||
|
Assert.assertEquals(0, n0);
|
||||||
|
Assert.assertEquals(1, n1);
|
||||||
|
Assert.assertEquals(13, n7);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToBinary() {
|
||||||
|
String b0 = recursion.toBinary(0);
|
||||||
|
String b1 = recursion.toBinary(1);
|
||||||
|
String b10 = recursion.toBinary(10);
|
||||||
|
|
||||||
|
Assert.assertEquals("0", b0);
|
||||||
|
Assert.assertEquals("1", b1);
|
||||||
|
Assert.assertEquals("1010", b10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalculateTreeHeight() {
|
||||||
|
BinaryNode root = new BinaryNode(1);
|
||||||
|
root.setLeft(new BinaryNode(1));
|
||||||
|
root.setRight(new BinaryNode(1));
|
||||||
|
|
||||||
|
root.getLeft().setLeft(new BinaryNode(1));
|
||||||
|
root.getLeft().getLeft().setRight(new BinaryNode(1));
|
||||||
|
root.getLeft().getLeft().getRight().setLeft(new BinaryNode(1));
|
||||||
|
|
||||||
|
root.getRight().setLeft(new BinaryNode(1));
|
||||||
|
root.getRight().getLeft().setRight(new BinaryNode(1));
|
||||||
|
|
||||||
|
int height = recursion.calculateTreeHeight(root);
|
||||||
|
|
||||||
|
Assert.assertEquals(4, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.resourcebundle;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class ExampleResourceUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetBundleExampleResourceForLocalePlPl_thenItShouldInheritPropertiesGreetingAndLanguage() {
|
||||||
|
Locale plLocale = new Locale("pl", "PL");
|
||||||
|
|
||||||
|
ResourceBundle exampleBundle = ResourceBundle.getBundle("com.baeldung.resourcebundle.ExampleResource", plLocale);
|
||||||
|
|
||||||
|
assertTrue(exampleBundle.keySet()
|
||||||
|
.containsAll(Arrays.asList("toUsdRate", "cities", "greeting", "currency", "language")));
|
||||||
|
assertEquals(exampleBundle.getString("greeting"), "cześć");
|
||||||
|
assertEquals(exampleBundle.getObject("toUsdRate"), new BigDecimal("3.401"));
|
||||||
|
assertArrayEquals(exampleBundle.getStringArray("cities"), new String[] { "Warsaw", "Cracow" });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetBundleExampleResourceForLocaleUs_thenItShouldContainOnlyGreeting() {
|
||||||
|
Locale usLocale = Locale.US;
|
||||||
|
|
||||||
|
ResourceBundle exampleBundle = ResourceBundle.getBundle("com.baeldung.resourcebundle.ExampleResource", usLocale);
|
||||||
|
|
||||||
|
assertFalse(exampleBundle.keySet()
|
||||||
|
.containsAll(Arrays.asList("toUsdRate", "cities", "currency", "language")));
|
||||||
|
assertTrue(exampleBundle.keySet()
|
||||||
|
.containsAll(Arrays.asList("greeting")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.baeldung.resourcebundle;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class PropertyResourceUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLocaleUsAsDefualt_whenGetBundleForLocalePlPl_thenItShouldContain3ButtonsAnd1Label() {
|
||||||
|
Locale.setDefault(Locale.US);
|
||||||
|
|
||||||
|
ResourceBundle bundle = ResourceBundle.getBundle("resourcebundle.resource", new Locale("pl", "PL"));
|
||||||
|
|
||||||
|
assertTrue(bundle.keySet()
|
||||||
|
.containsAll(Arrays.asList("backButton", "helloLabel", "cancelButton", "continueButton", "helloLabelNoEncoding")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLocaleUsAsDefualt_whenGetBundleForLocaleFrFr_thenItShouldContainKeys1To3AndKey4() {
|
||||||
|
Locale.setDefault(Locale.US);
|
||||||
|
|
||||||
|
ResourceBundle bundle = ResourceBundle.getBundle("resourcebundle.resource", new Locale("fr", "FR"));
|
||||||
|
|
||||||
|
assertTrue(bundle.keySet()
|
||||||
|
.containsAll(Arrays.asList("deleteButton", "helloLabel", "cancelButton", "continueButton")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLocaleChinaAsDefualt_whenGetBundleForLocaleFrFr_thenItShouldOnlyContainKeys1To3() {
|
||||||
|
Locale.setDefault(Locale.CHINA);
|
||||||
|
|
||||||
|
ResourceBundle bundle = ResourceBundle.getBundle("resourcebundle.resource", new Locale("fr", "FR"));
|
||||||
|
|
||||||
|
assertTrue(bundle.keySet()
|
||||||
|
.containsAll(Arrays.asList("continueButton", "helloLabel", "cancelButton")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLocaleChinaAsDefualt_whenGetBundleForLocaleFrFrAndExampleControl_thenItShouldOnlyContainKey5() {
|
||||||
|
Locale.setDefault(Locale.CHINA);
|
||||||
|
|
||||||
|
ResourceBundle bundle = ResourceBundle.getBundle("resourcebundle.resource", new Locale("fr", "FR"), new ExampleControl());
|
||||||
|
|
||||||
|
assertTrue(bundle.keySet()
|
||||||
|
.containsAll(Arrays.asList("backButton", "helloLabel")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenValuesDifferentlyEncoded_whenGetBundleForLocalePlPl_thenItShouldContain3ButtonsAnd1Label() {
|
||||||
|
ResourceBundle bundle = ResourceBundle.getBundle("resourcebundle.resource", new Locale("pl", "PL"));
|
||||||
|
|
||||||
|
assertEquals(bundle.getString("helloLabel"), "cześć");
|
||||||
|
assertEquals(bundle.getString("helloLabelNoEncoding"), "czeÅ\u009BÄ\u0087");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,4 +17,4 @@
|
||||||
- [Sealed Classes in Kotlin](http://www.baeldung.com/kotlin-sealed-classes)
|
- [Sealed Classes in Kotlin](http://www.baeldung.com/kotlin-sealed-classes)
|
||||||
- [JUnit 5 for Kotlin Developers](http://www.baeldung.com/junit-5-kotlin)
|
- [JUnit 5 for Kotlin Developers](http://www.baeldung.com/junit-5-kotlin)
|
||||||
- [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods)
|
- [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods)
|
||||||
|
- [Infix Functions in Kotlin](http://www.baeldung.com/kotlin-infix-functions)
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
## Google Cloud Tutorial Project
|
||||||
|
|
||||||
|
### Relevant Article:
|
||||||
|
- [Intro to Google Cloud Storage With Java](http://www.baeldung.com/intro-to-google-cloud-storage-with-java/)
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
This Maven project contains the Java code for the article linked above.
|
||||||
|
|
||||||
|
### Package Organization
|
||||||
|
Java classes for the intro tutorial are in the org.baeldung.google.cloud package. Please note that Google Cloud requires
|
||||||
|
a user account and credentials, as explained in the tutorial.
|
||||||
|
|
||||||
|
|
||||||
|
### Running the tests
|
||||||
|
|
||||||
|
```
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>google-cloud</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>google-cloud</name>
|
||||||
|
<description>Google Cloud Tutorials</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.cloud</groupId>
|
||||||
|
<artifactId>google-cloud-storage</artifactId>
|
||||||
|
<version>1.16.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<!-- Check for the most recent available version: https://projectlombok.org/changelog.html -->
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<lombok.version>1.16.18</lombok.version>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,105 @@
|
||||||
|
package com.baeldung.google.cloud.storage;
|
||||||
|
|
||||||
|
import com.google.api.gax.paging.Page;
|
||||||
|
import com.google.auth.Credentials;
|
||||||
|
import com.google.auth.oauth2.GoogleCredentials;
|
||||||
|
import com.google.cloud.storage.*;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple class for creating, reading and modifying text blobs on Google Cloud
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class GoogleCloudStorage {
|
||||||
|
|
||||||
|
private Storage storage;
|
||||||
|
private Bucket bucket;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
// Use this variation to read the Google authorization JSON from the resources directory with a path
|
||||||
|
// and a project name.
|
||||||
|
GoogleCloudStorage googleCloudStorage =
|
||||||
|
new GoogleCloudStorage("google-cloud/src/main/resources/google_auth.json", "baeldung-cloud-tutorial");
|
||||||
|
|
||||||
|
// Bucket require globally unique names, so you'll probably need to change this
|
||||||
|
Bucket bucket = googleCloudStorage.getBucket("baeldung-1-bucket");
|
||||||
|
|
||||||
|
// Save a simple string
|
||||||
|
BlobId blobId = googleCloudStorage.saveString("my-first-blob", "Hi there!", bucket);
|
||||||
|
|
||||||
|
// Get it by blob id this time
|
||||||
|
String value = googleCloudStorage.getString(blobId);
|
||||||
|
|
||||||
|
log.info("Read data: {}", value);
|
||||||
|
|
||||||
|
googleCloudStorage.updateString(blobId, "Bye now!");
|
||||||
|
|
||||||
|
// Get the string by blob name
|
||||||
|
value = googleCloudStorage.getString("my-first-blob");
|
||||||
|
|
||||||
|
log.info("Read modified data: {}", value);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Use path and project name
|
||||||
|
private GoogleCloudStorage(String pathToConfig, String projectId) throws IOException {
|
||||||
|
Credentials credentials = GoogleCredentials.fromStream(new FileInputStream(pathToConfig));
|
||||||
|
storage = StorageOptions.newBuilder().setCredentials(credentials).setProjectId(projectId).build().getService();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for bucket existence and create if needed.
|
||||||
|
private Bucket getBucket(String bucketName) {
|
||||||
|
bucket = storage.get(bucketName);
|
||||||
|
if (bucket == null) {
|
||||||
|
System.out.println("Creating new bucket.");
|
||||||
|
bucket = storage.create(BucketInfo.of(bucketName));
|
||||||
|
}
|
||||||
|
return bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save a string to a blob
|
||||||
|
private BlobId saveString(String blobName, String value, Bucket bucket) {
|
||||||
|
byte[] bytes = value.getBytes(UTF_8);
|
||||||
|
Blob blob = bucket.create(blobName, bytes);
|
||||||
|
return blob.getBlobId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get a blob by id
|
||||||
|
private String getString(BlobId blobId) {
|
||||||
|
Blob blob = storage.get(blobId);
|
||||||
|
return new String(blob.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get a blob by name
|
||||||
|
private String getString(String name) {
|
||||||
|
Page<Blob> blobs = bucket.list();
|
||||||
|
for (Blob blob: blobs.getValues()) {
|
||||||
|
if (name.equals(blob.getName())) {
|
||||||
|
return new String(blob.getContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "Blob not found";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update a blob
|
||||||
|
private void updateString(BlobId blobId, String newString) throws IOException {
|
||||||
|
Blob blob = storage.get(blobId);
|
||||||
|
if (blob != null) {
|
||||||
|
WritableByteChannel channel = blob.writer();
|
||||||
|
channel.write(ByteBuffer.wrap(newString.getBytes(UTF_8)));
|
||||||
|
channel.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
- [Guide to Guava’s Ordering](http://www.baeldung.com/guava-ordering)
|
- [Guide to Guava’s Ordering](http://www.baeldung.com/guava-ordering)
|
||||||
- [Guide to Guava’s PreConditions](http://www.baeldung.com/guava-preconditions)
|
- [Guide to Guava’s PreConditions](http://www.baeldung.com/guava-preconditions)
|
||||||
- [Introduction to Guava CacheLoader](http://www.baeldung.com/guava-cacheloader)
|
- [Introduction to Guava CacheLoader](http://www.baeldung.com/guava-cacheloader)
|
||||||
|
- [Introduction to Guava Memoizer](http://www.baeldung.com/guava-memoizer)
|
||||||
- [Guide to Guava’s EventBus](http://www.baeldung.com/guava-eventbus)
|
- [Guide to Guava’s EventBus](http://www.baeldung.com/guava-eventbus)
|
||||||
- [Guide to Guava Multimap](http://www.baeldung.com/guava-multimap)
|
- [Guide to Guava Multimap](http://www.baeldung.com/guava-multimap)
|
||||||
- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset)
|
- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset)
|
||||||
|
|
|
@ -16,6 +16,24 @@
|
||||||
<artifactId>log4j-core</artifactId>
|
<artifactId>log4j-core</artifactId>
|
||||||
<version>${log4j2.version}</version>
|
<version>${log4j2.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-core</artifactId>
|
||||||
|
<version>${org.hamcrest.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-library</artifactId>
|
||||||
|
<version>${org.hamcrest.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-all</artifactId>
|
||||||
|
<version>${org.hamcrest.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -32,5 +50,6 @@
|
||||||
</build>
|
</build>
|
||||||
<properties>
|
<properties>
|
||||||
<log4j2.version>2.8.2</log4j2.version>
|
<log4j2.version>2.8.2</log4j2.version>
|
||||||
|
<org.hamcrest.version>1.3</org.hamcrest.version>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.stackify.stream;
|
||||||
|
|
||||||
|
public class Employee {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private Double salary;
|
||||||
|
|
||||||
|
public Employee(Integer id, String name, Double salary) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.salary = salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getSalary() {
|
||||||
|
return salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSalary(Double salary) {
|
||||||
|
this.salary = salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void salaryIncrement(Double percentage) {
|
||||||
|
Double newSalary = salary + percentage * salary / 100;
|
||||||
|
setSalary(newSalary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "Id: " + id + " Name:" + name + " Price:" + salary;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.stackify.stream;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class EmployeeRepository {
|
||||||
|
private List<Employee> empList;
|
||||||
|
|
||||||
|
public EmployeeRepository(List<Employee> empList) {
|
||||||
|
this.empList = empList;
|
||||||
|
|
||||||
|
}
|
||||||
|
public Employee findById(Integer id) {
|
||||||
|
for (Employee emp : empList) {
|
||||||
|
if (emp.getId() == id) {
|
||||||
|
return emp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,455 @@
|
||||||
|
package com.stackify.stream;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.contains;
|
||||||
|
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.DoubleSummaryStatistics;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
|
import java.util.function.BinaryOperator;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class EmployeeTest {
|
||||||
|
private String fileName = "src/test/resources/test.txt";
|
||||||
|
|
||||||
|
private static Employee[] arrayOfEmps = {
|
||||||
|
new Employee(1, "Jeff Bezos", 100000.0),
|
||||||
|
new Employee(2, "Bill Gates", 200000.0),
|
||||||
|
new Employee(3, "Mark Zuckerberg", 300000.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
private static List<Employee> empList = Arrays.asList(arrayOfEmps);
|
||||||
|
private static EmployeeRepository employeeRepository = new EmployeeRepository(empList);
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanup() throws IOException {
|
||||||
|
Files.deleteIfExists(Paths.get(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetStreamFromList_ObtainStream() {
|
||||||
|
assert(empList.stream() instanceof Stream<?>);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetStreamFromArray_ObtainStream() {
|
||||||
|
assert(Stream.of(arrayOfEmps) instanceof Stream<?>);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetStreamFromElements_ObtainStream() {
|
||||||
|
assert(Stream.of(arrayOfEmps[0], arrayOfEmps[1], arrayOfEmps[2]) instanceof Stream<?>);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBuildStreamFromElements_ObtainStream() {
|
||||||
|
Stream.Builder<Employee> empStreamBuilder = Stream.builder();
|
||||||
|
|
||||||
|
empStreamBuilder.accept(arrayOfEmps[0]);
|
||||||
|
empStreamBuilder.accept(arrayOfEmps[1]);
|
||||||
|
empStreamBuilder.accept(arrayOfEmps[2]);
|
||||||
|
|
||||||
|
Stream<Employee> empStream = empStreamBuilder.build();
|
||||||
|
|
||||||
|
assert(empStream instanceof Stream<?>);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenIncrementSalaryForEachEmployee_thenApplyNewSalary() {
|
||||||
|
Employee[] arrayOfEmps = {
|
||||||
|
new Employee(1, "Jeff Bezos", 100000.0),
|
||||||
|
new Employee(2, "Bill Gates", 200000.0),
|
||||||
|
new Employee(3, "Mark Zuckerberg", 300000.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
List<Employee> empList = Arrays.asList(arrayOfEmps);
|
||||||
|
|
||||||
|
empList.stream().forEach(e -> e.salaryIncrement(10.0));
|
||||||
|
|
||||||
|
assertThat(empList, contains(
|
||||||
|
hasProperty("salary", equalTo(110000.0)),
|
||||||
|
hasProperty("salary", equalTo(220000.0)),
|
||||||
|
hasProperty("salary", equalTo(330000.0))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenIncrementSalaryUsingPeek_thenApplyNewSalary() {
|
||||||
|
Employee[] arrayOfEmps = {
|
||||||
|
new Employee(1, "Jeff Bezos", 100000.0),
|
||||||
|
new Employee(2, "Bill Gates", 200000.0),
|
||||||
|
new Employee(3, "Mark Zuckerberg", 300000.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
List<Employee> empList = Arrays.asList(arrayOfEmps);
|
||||||
|
|
||||||
|
empList.stream()
|
||||||
|
.peek(e -> e.salaryIncrement(10.0))
|
||||||
|
.peek(System.out::println)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertThat(empList, contains(
|
||||||
|
hasProperty("salary", equalTo(110000.0)),
|
||||||
|
hasProperty("salary", equalTo(220000.0)),
|
||||||
|
hasProperty("salary", equalTo(330000.0))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenMapIdToEmployees_thenGetEmployeeStream() {
|
||||||
|
Integer[] empIds = { 1, 2, 3 };
|
||||||
|
|
||||||
|
List<Employee> employees = Stream.of(empIds)
|
||||||
|
.map(employeeRepository::findById)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(employees.size(), empIds.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFlatMapEmployeeNames_thenGetNameStream() {
|
||||||
|
List<List<String>> namesNested = Arrays.asList(
|
||||||
|
Arrays.asList("Jeff", "Bezos"),
|
||||||
|
Arrays.asList("Bill", "Gates"),
|
||||||
|
Arrays.asList("Mark", "Zuckerberg"));
|
||||||
|
|
||||||
|
List<String> namesFlatStream = namesNested.stream()
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(namesFlatStream.size(), namesNested.size() * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFilterEmployees_thenGetFilteredStream() {
|
||||||
|
Integer[] empIds = { 1, 2, 3, 4 };
|
||||||
|
|
||||||
|
List<Employee> employees = Stream.of(empIds)
|
||||||
|
.map(employeeRepository::findById)
|
||||||
|
.filter(e -> e != null)
|
||||||
|
.filter(e -> e.getSalary() > 200000)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(Arrays.asList(arrayOfEmps[2]), employees);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFindFirst_thenGetFirstEmployeeInStream() {
|
||||||
|
Integer[] empIds = { 1, 2, 3, 4 };
|
||||||
|
|
||||||
|
Employee employee = Stream.of(empIds)
|
||||||
|
.map(employeeRepository::findById)
|
||||||
|
.filter(e -> e != null)
|
||||||
|
.filter(e -> e.getSalary() > 100000)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
assertEquals(employee.getSalary(), new Double(200000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCollectStreamToList_thenGetList() {
|
||||||
|
List<Employee> employees = empList.stream().collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(empList, employees);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamToArray_thenGetArray() {
|
||||||
|
Employee[] employees = empList.stream().toArray(Employee[]::new);
|
||||||
|
|
||||||
|
assertThat(empList.toArray(), equalTo(employees));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamCount_thenGetElementCount() {
|
||||||
|
Long empCount = empList.stream()
|
||||||
|
.filter(e -> e.getSalary() > 200000)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
assertEquals(empCount, new Long(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenLimitInfiniteStream_thenGetFiniteElements() {
|
||||||
|
Stream<Integer> infiniteStream = Stream.iterate(2, i -> i * 2);
|
||||||
|
|
||||||
|
List<Integer> collect = infiniteStream
|
||||||
|
.skip(3)
|
||||||
|
.limit(5)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(collect, Arrays.asList(16, 32, 64, 128, 256));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSortStream_thenGetSortedStream() {
|
||||||
|
List<Employee> employees = empList.stream()
|
||||||
|
.sorted((e1, e2) -> e1.getName().compareTo(e2.getName()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(employees.get(0).getName(), "Bill Gates");
|
||||||
|
assertEquals(employees.get(1).getName(), "Jeff Bezos");
|
||||||
|
assertEquals(employees.get(2).getName(), "Mark Zuckerberg");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFindMin_thenGetMinElementFromStream() {
|
||||||
|
Employee firstEmp = empList.stream()
|
||||||
|
.min((e1, e2) -> e1.getId() - e2.getId())
|
||||||
|
.orElseThrow(NoSuchElementException::new);
|
||||||
|
|
||||||
|
assertEquals(firstEmp.getId(), new Integer(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFindMax_thenGetMaxElementFromStream() {
|
||||||
|
Employee maxSalEmp = empList.stream()
|
||||||
|
.max(Comparator.comparing(Employee::getSalary))
|
||||||
|
.orElseThrow(NoSuchElementException::new);
|
||||||
|
|
||||||
|
assertEquals(maxSalEmp.getSalary(), new Double(300000.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenApplyDistinct_thenRemoveDuplicatesFromStream() {
|
||||||
|
List<Integer> intList = Arrays.asList(2, 5, 3, 2, 4, 3);
|
||||||
|
List<Integer> distinctIntList = intList.stream().distinct().collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(distinctIntList, Arrays.asList(2, 5, 3, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenApplyMatch_thenReturnBoolean() {
|
||||||
|
List<Integer> intList = Arrays.asList(2, 4, 5, 6, 8);
|
||||||
|
|
||||||
|
boolean allEven = intList.stream().allMatch(i -> i % 2 == 0);
|
||||||
|
boolean oneEven = intList.stream().anyMatch(i -> i % 2 == 0);
|
||||||
|
boolean noneMultipleOfThree = intList.stream().noneMatch(i -> i % 3 == 0);
|
||||||
|
|
||||||
|
assertEquals(allEven, false);
|
||||||
|
assertEquals(oneEven, true);
|
||||||
|
assertEquals(noneMultipleOfThree, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFindMaxOnIntStream_thenGetMaxInteger() {
|
||||||
|
Integer latestEmpId = empList.stream()
|
||||||
|
.mapToInt(Employee::getId)
|
||||||
|
.max()
|
||||||
|
.orElseThrow(NoSuchElementException::new);
|
||||||
|
|
||||||
|
assertEquals(latestEmpId, new Integer(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenApplySumOnIntStream_thenGetSum() {
|
||||||
|
Double avgSal = empList.stream()
|
||||||
|
.mapToDouble(Employee::getSalary)
|
||||||
|
.average()
|
||||||
|
.orElseThrow(NoSuchElementException::new);
|
||||||
|
|
||||||
|
assertEquals(avgSal, new Double(200000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenApplyReduceOnStream_thenGetValue() {
|
||||||
|
Double sumSal = empList.stream()
|
||||||
|
.map(Employee::getSalary)
|
||||||
|
.reduce(0.0, Double::sum);
|
||||||
|
|
||||||
|
assertEquals(sumSal, new Double(600000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCollectByJoining_thenGetJoinedString() {
|
||||||
|
String empNames = empList.stream()
|
||||||
|
.map(Employee::getName)
|
||||||
|
.collect(Collectors.joining(", "))
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
assertEquals(empNames, "Jeff Bezos, Bill Gates, Mark Zuckerberg");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCollectBySet_thenGetSet() {
|
||||||
|
Set<String> empNames = empList.stream()
|
||||||
|
.map(Employee::getName)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
assertEquals(empNames.size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenToVectorCollection_thenGetVector() {
|
||||||
|
Vector<String> empNames = empList.stream()
|
||||||
|
.map(Employee::getName)
|
||||||
|
.collect(Collectors.toCollection(Vector::new));
|
||||||
|
|
||||||
|
assertEquals(empNames.size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenApplySummarizing_thenGetBasicStats() {
|
||||||
|
DoubleSummaryStatistics stats = empList.stream()
|
||||||
|
.collect(Collectors.summarizingDouble(Employee::getSalary));
|
||||||
|
|
||||||
|
assertEquals(stats.getCount(), 3);
|
||||||
|
assertEquals(stats.getSum(), 600000.0, 0);
|
||||||
|
assertEquals(stats.getMin(), 100000.0, 0);
|
||||||
|
assertEquals(stats.getMax(), 300000.0, 0);
|
||||||
|
assertEquals(stats.getAverage(), 200000.0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenApplySummaryStatistics_thenGetBasicStats() {
|
||||||
|
DoubleSummaryStatistics stats = empList.stream()
|
||||||
|
.mapToDouble(Employee::getSalary)
|
||||||
|
.summaryStatistics();
|
||||||
|
|
||||||
|
assertEquals(stats.getCount(), 3);
|
||||||
|
assertEquals(stats.getSum(), 600000.0, 0);
|
||||||
|
assertEquals(stats.getMin(), 100000.0, 0);
|
||||||
|
assertEquals(stats.getMax(), 300000.0, 0);
|
||||||
|
assertEquals(stats.getAverage(), 200000.0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamPartition_thenGetMap() {
|
||||||
|
List<Integer> intList = Arrays.asList(2, 4, 5, 6, 8);
|
||||||
|
Map<Boolean, List<Integer>> isEven = intList.stream().collect(
|
||||||
|
Collectors.partitioningBy(i -> i % 2 == 0));
|
||||||
|
|
||||||
|
assertEquals(isEven.get(true).size(), 4);
|
||||||
|
assertEquals(isEven.get(false).size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamGroupingBy_thenGetMap() {
|
||||||
|
Map<Character, List<Employee>> groupByAlphabet = empList.stream().collect(
|
||||||
|
Collectors.groupingBy(e -> new Character(e.getName().charAt(0))));
|
||||||
|
|
||||||
|
assertEquals(groupByAlphabet.get('B').get(0).getName(), "Bill Gates");
|
||||||
|
assertEquals(groupByAlphabet.get('J').get(0).getName(), "Jeff Bezos");
|
||||||
|
assertEquals(groupByAlphabet.get('M').get(0).getName(), "Mark Zuckerberg");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamMapping_thenGetMap() {
|
||||||
|
Map<Character, List<Integer>> idGroupedByAlphabet = empList.stream().collect(
|
||||||
|
Collectors.groupingBy(e -> new Character(e.getName().charAt(0)),
|
||||||
|
Collectors.mapping(Employee::getId, Collectors.toList())));
|
||||||
|
|
||||||
|
assertEquals(idGroupedByAlphabet.get('B').get(0), new Integer(2));
|
||||||
|
assertEquals(idGroupedByAlphabet.get('J').get(0), new Integer(1));
|
||||||
|
assertEquals(idGroupedByAlphabet.get('M').get(0), new Integer(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamReducing_thenGetValue() {
|
||||||
|
Double percentage = 10.0;
|
||||||
|
Double salIncrOverhead = empList.stream().collect(Collectors.reducing(
|
||||||
|
0.0, e -> e.getSalary() * percentage / 100, (s1, s2) -> s1 + s2));
|
||||||
|
|
||||||
|
assertEquals(salIncrOverhead, 60000.0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamGroupingAndReducing_thenGetMap() {
|
||||||
|
Comparator<Employee> byNameLength = Comparator.comparing(Employee::getName);
|
||||||
|
|
||||||
|
Map<Character, Optional<Employee>> longestNameByAlphabet = empList.stream().collect(
|
||||||
|
Collectors.groupingBy(e -> new Character(e.getName().charAt(0)),
|
||||||
|
Collectors.reducing(BinaryOperator.maxBy(byNameLength))));
|
||||||
|
|
||||||
|
assertEquals(longestNameByAlphabet.get('B').get().getName(), "Bill Gates");
|
||||||
|
assertEquals(longestNameByAlphabet.get('J').get().getName(), "Jeff Bezos");
|
||||||
|
assertEquals(longestNameByAlphabet.get('M').get().getName(), "Mark Zuckerberg");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenParallelStream_thenPerformOperationsInParallel() {
|
||||||
|
Employee[] arrayOfEmps = {
|
||||||
|
new Employee(1, "Jeff Bezos", 100000.0),
|
||||||
|
new Employee(2, "Bill Gates", 200000.0),
|
||||||
|
new Employee(3, "Mark Zuckerberg", 300000.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
List<Employee> empList = Arrays.asList(arrayOfEmps);
|
||||||
|
|
||||||
|
empList.stream().parallel().forEach(e -> e.salaryIncrement(10.0));
|
||||||
|
|
||||||
|
assertThat(empList, contains(
|
||||||
|
hasProperty("salary", equalTo(110000.0)),
|
||||||
|
hasProperty("salary", equalTo(220000.0)),
|
||||||
|
hasProperty("salary", equalTo(330000.0))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGenerateStream_thenGetInfiniteStream() {
|
||||||
|
Stream.generate(Math::random)
|
||||||
|
.limit(5)
|
||||||
|
.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenIterateStream_thenGetInfiniteStream() {
|
||||||
|
Stream<Integer> evenNumStream = Stream.iterate(2, i -> i * 2);
|
||||||
|
|
||||||
|
List<Integer> collect = evenNumStream
|
||||||
|
.limit(5)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
assertEquals(collect, Arrays.asList(2, 4, 8, 16, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStreamToFile_thenGetFile() throws IOException {
|
||||||
|
String[] words = {
|
||||||
|
"hello",
|
||||||
|
"refer",
|
||||||
|
"world",
|
||||||
|
"level"
|
||||||
|
};
|
||||||
|
|
||||||
|
try (PrintWriter pw = new PrintWriter(
|
||||||
|
Files.newBufferedWriter(Paths.get(fileName)))) {
|
||||||
|
Stream.of(words).forEach(pw::println);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getPalindrome(Stream<String> stream, int length) {
|
||||||
|
return stream.filter(s -> s.length() == length)
|
||||||
|
.filter(s -> s.compareToIgnoreCase(
|
||||||
|
new StringBuilder(s).reverse().toString()) == 0)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFileToStream_thenGetStream() throws IOException {
|
||||||
|
whenStreamToFile_thenGetFile();
|
||||||
|
|
||||||
|
List<String> str = getPalindrome(Files.lines(Paths.get(fileName)), 5);
|
||||||
|
assertThat(str, contains("refer", "level"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,31 +11,49 @@ public class PersonNameConverter implements AttributeConverter<PersonName, Strin
|
||||||
private static final String SEPARATOR = ", ";
|
private static final String SEPARATOR = ", ";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String convertToDatabaseColumn(PersonName person) {
|
public String convertToDatabaseColumn(PersonName personName) {
|
||||||
|
if (personName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (person.getSurname() != null) {
|
if (personName.getSurname() != null && !personName.getSurname()
|
||||||
sb.append(person.getSurname());
|
.isEmpty()) {
|
||||||
|
sb.append(personName.getSurname());
|
||||||
sb.append(SEPARATOR);
|
sb.append(SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (person.getName() != null) {
|
if (personName.getName() != null && !personName.getName()
|
||||||
sb.append(person.getName());
|
.isEmpty()) {
|
||||||
|
sb.append(personName.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PersonName convertToEntityAttribute(String dbPerson) {
|
public PersonName convertToEntityAttribute(String dbPersonName) {
|
||||||
String[] pieces = dbPerson.split(SEPARATOR);
|
if (dbPersonName == null || dbPersonName.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (pieces == null || pieces.length != 2) {
|
String[] pieces = dbPersonName.split(SEPARATOR);
|
||||||
|
|
||||||
|
if (pieces == null || pieces.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
PersonName personName = new PersonName();
|
PersonName personName = new PersonName();
|
||||||
personName.setSurname(pieces[0]);
|
String firstPiece = !pieces[0].isEmpty() ? pieces[0] : null;
|
||||||
|
if (dbPersonName.contains(SEPARATOR)) {
|
||||||
|
personName.setSurname(firstPiece);
|
||||||
|
|
||||||
|
if (pieces.length >= 2 && pieces[1] != null && !pieces[1].isEmpty()) {
|
||||||
personName.setName(pieces[1]);
|
personName.setName(pieces[1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
personName.setName(firstPiece);
|
||||||
|
}
|
||||||
|
|
||||||
return personName;
|
return personName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,4 +71,130 @@ public class PersonNameConverterTest {
|
||||||
.getSurname(), surname);
|
.getSurname(), surname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonNameNull_WhenSaving_ThenNullStored() {
|
||||||
|
final String name = null;
|
||||||
|
final String surname = null;
|
||||||
|
|
||||||
|
PersonName personName = new PersonName();
|
||||||
|
personName.setName(name);
|
||||||
|
personName.setSurname(surname);
|
||||||
|
|
||||||
|
Person person = new Person();
|
||||||
|
person.setPersonName(personName);
|
||||||
|
|
||||||
|
Long id = (Long) session.save(person);
|
||||||
|
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
String dbPersonName = (String) session.createNativeQuery("select p.personName from PersonTable p where p.id = :id")
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals("", dbPersonName);
|
||||||
|
|
||||||
|
Person dbPerson = session.createNativeQuery("select * from PersonTable p where p.id = :id", Person.class)
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals(dbPerson.getPersonName(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonNameWithoutName_WhenSaving_ThenNotNameStored() {
|
||||||
|
final String name = null;
|
||||||
|
final String surname = "surname";
|
||||||
|
|
||||||
|
PersonName personName = new PersonName();
|
||||||
|
personName.setName(name);
|
||||||
|
personName.setSurname(surname);
|
||||||
|
|
||||||
|
Person person = new Person();
|
||||||
|
person.setPersonName(personName);
|
||||||
|
|
||||||
|
Long id = (Long) session.save(person);
|
||||||
|
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
String dbPersonName = (String) session.createNativeQuery("select p.personName from PersonTable p where p.id = :id")
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals("surname, ", dbPersonName);
|
||||||
|
|
||||||
|
Person dbPerson = session.createNativeQuery("select * from PersonTable p where p.id = :id", Person.class)
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals(dbPerson.getPersonName()
|
||||||
|
.getName(), name);
|
||||||
|
assertEquals(dbPerson.getPersonName()
|
||||||
|
.getSurname(), surname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonNameWithoutSurName_WhenSaving_ThenNotSurNameStored() {
|
||||||
|
final String name = "name";
|
||||||
|
final String surname = null;
|
||||||
|
|
||||||
|
PersonName personName = new PersonName();
|
||||||
|
personName.setName(name);
|
||||||
|
personName.setSurname(surname);
|
||||||
|
|
||||||
|
Person person = new Person();
|
||||||
|
person.setPersonName(personName);
|
||||||
|
|
||||||
|
Long id = (Long) session.save(person);
|
||||||
|
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
String dbPersonName = (String) session.createNativeQuery("select p.personName from PersonTable p where p.id = :id")
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals("name", dbPersonName);
|
||||||
|
|
||||||
|
Person dbPerson = session.createNativeQuery("select * from PersonTable p where p.id = :id", Person.class)
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals(dbPerson.getPersonName()
|
||||||
|
.getName(), name);
|
||||||
|
assertEquals(dbPerson.getPersonName()
|
||||||
|
.getSurname(), surname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonNameEmptyFields_WhenSaving_ThenFielsNotStored() {
|
||||||
|
final String name = "";
|
||||||
|
final String surname = "";
|
||||||
|
|
||||||
|
PersonName personName = new PersonName();
|
||||||
|
personName.setName(name);
|
||||||
|
personName.setSurname(surname);
|
||||||
|
|
||||||
|
Person person = new Person();
|
||||||
|
person.setPersonName(personName);
|
||||||
|
|
||||||
|
Long id = (Long) session.save(person);
|
||||||
|
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
String dbPersonName = (String) session.createNativeQuery("select p.personName from PersonTable p where p.id = :id")
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals("", dbPersonName);
|
||||||
|
|
||||||
|
Person dbPerson = session.createNativeQuery("select * from PersonTable p where p.id = :id", Person.class)
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals(dbPerson.getPersonName(), null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -22,10 +21,15 @@
|
||||||
<mysql.connector.java.version>5.1.45</mysql.connector.java.version>
|
<mysql.connector.java.version>5.1.45</mysql.connector.java.version>
|
||||||
<sun.tools.version>1.7.0</sun.tools.version>
|
<sun.tools.version>1.7.0</sun.tools.version>
|
||||||
<jackson.version>1.8.2</jackson.version>
|
<jackson.version>1.8.2</jackson.version>
|
||||||
<junit.version>4.11</junit.version>
|
<junit.version>4.12</junit.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/webapp/WEB-INF</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
@ -86,6 +90,13 @@
|
||||||
<systemPath>${java.home}/../lib/tools.jar</systemPath>
|
<systemPath>${java.home}/../lib/tools.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.javalite</groupId>
|
||||||
|
<artifactId>activeweb-testing</artifactId>
|
||||||
|
<version>1.15</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|
|
@ -3,7 +3,15 @@ package app.config;
|
||||||
import org.javalite.activeweb.AppContext;
|
import org.javalite.activeweb.AppContext;
|
||||||
import org.javalite.activeweb.Bootstrap;
|
import org.javalite.activeweb.Bootstrap;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
import app.services.ArticleServiceModule;
|
||||||
|
|
||||||
public class AppBootstrap extends Bootstrap {
|
public class AppBootstrap extends Bootstrap {
|
||||||
public void init(AppContext context) {
|
public void init(AppContext context) {
|
||||||
}
|
}
|
||||||
|
public Injector getInjector() {
|
||||||
|
return Guice.createInjector(new ArticleServiceModule());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package app.controllers;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.javalite.activeweb.AppController;
|
||||||
|
|
||||||
|
import app.services.ArticleService;
|
||||||
|
|
||||||
|
public class ArticleController extends AppController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ArticleService articleService;
|
||||||
|
|
||||||
|
public void index() {
|
||||||
|
view("articles", articleService.getArticles());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void search() {
|
||||||
|
|
||||||
|
String keyword = param("key");
|
||||||
|
if (null != keyword) {
|
||||||
|
assign("article", articleService.search(keyword));
|
||||||
|
} else {
|
||||||
|
render("/common/error");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package app.controllers;
|
||||||
|
|
||||||
|
import org.javalite.activeweb.AppController;
|
||||||
|
|
||||||
|
public class HomeController extends AppController {
|
||||||
|
|
||||||
|
public void index() {
|
||||||
|
render("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package app.models;
|
||||||
|
|
||||||
|
public class Article {
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String author;
|
||||||
|
private String words;
|
||||||
|
private String date;
|
||||||
|
|
||||||
|
public Article(String title, String author, String words, String date) {
|
||||||
|
super();
|
||||||
|
this.title = title;
|
||||||
|
this.author = author;
|
||||||
|
this.words = words;
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWords() {
|
||||||
|
return words;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWords(String words) {
|
||||||
|
this.words = words;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(String date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package app.services;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import app.models.Article;
|
||||||
|
|
||||||
|
public interface ArticleService {
|
||||||
|
|
||||||
|
List<Article> getArticles();
|
||||||
|
|
||||||
|
Article search(String keyword);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package app.services;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import app.models.Article;
|
||||||
|
|
||||||
|
public class ArticleServiceImpl implements ArticleService {
|
||||||
|
|
||||||
|
public List<Article> getArticles() {
|
||||||
|
return fetchArticles();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Article search(String keyword) {
|
||||||
|
Article ar = new Article("Article with " + keyword, "baeldung", "1250", Instant.now()
|
||||||
|
.toString());
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Article> fetchArticles() {
|
||||||
|
Article ar1 = new Article("Introduction to ActiveWeb", "baeldung", "1650", Instant.now()
|
||||||
|
.toString());
|
||||||
|
|
||||||
|
Article ar = new Article("Introduction to Mule", "baeldung", "1650", Instant.now()
|
||||||
|
.toString());
|
||||||
|
List<Article> articles = new ArrayList<Article>();
|
||||||
|
articles.add(ar);
|
||||||
|
articles.add(ar1);
|
||||||
|
return articles;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package app.services;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
|
||||||
|
public class ArticleServiceModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(ArticleService.class).to(ArticleServiceImpl.class)
|
||||||
|
.asEagerSingleton();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<@content for="title">Articles</@content>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Title</td>
|
||||||
|
<td>Author</td>
|
||||||
|
<td>Words #</td>
|
||||||
|
<td>Date Published</td>
|
||||||
|
</tr>
|
||||||
|
<#list articles as article>
|
||||||
|
<tr>
|
||||||
|
<td>${article.title}</td>
|
||||||
|
<td>${article.author}</td>
|
||||||
|
<td>${article.words}</td>
|
||||||
|
<td>${article.date}</td>
|
||||||
|
</tr>
|
||||||
|
</#list>
|
||||||
|
</table>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<@content for="title">Search</@content>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Title</td>
|
||||||
|
<td>Author</td>
|
||||||
|
<td>Words #</td>
|
||||||
|
<td>Date Published</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>${article.title}</td>
|
||||||
|
<td>${article.author}</td>
|
||||||
|
<td>${article.words}</td>
|
||||||
|
<td>${article.date}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<@content for="title">Simple Web App</@content>
|
||||||
|
|
||||||
|
<h2>Application error</h2>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<@content for="title">Simple Web App</@content>
|
||||||
|
|
||||||
|
<h2>Baeldung ActiveWeb Demo Application</h2>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<#setting url_escaping_charset='ISO-8859-1'>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="main">
|
||||||
|
<#include "header.ftl" >
|
||||||
|
<div class="content">
|
||||||
|
${page_content}
|
||||||
|
</div>
|
||||||
|
<#include "footer.ftl" >
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div class='footer'>
|
||||||
|
<p>2018 Baeldung. No Rights Reserved.</p>
|
||||||
|
</div>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<div class="header">
|
||||||
|
<h1><a href="${context_path}">Baeldung ActiveWeb Demo</a></h1>
|
||||||
|
</div>
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
<filter>
|
<filter>
|
||||||
<filter-name>dispatcher</filter-name>
|
<filter-name>dispatcher</filter-name>
|
||||||
<filter-class>org.javalite.activeweb.RequestDispatcher</filter-class>
|
<filter-class>org.javalite.activeweb.RequestDispatcher</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>root_controller</param-name>
|
||||||
|
<param-value>home</param-value>
|
||||||
|
</init-param>
|
||||||
<init-param>
|
<init-param>
|
||||||
<param-name>exclusions</param-name>
|
<param-name>exclusions</param-name>
|
||||||
<param-value>css,images,js,ico</param-value>
|
<param-value>css,images,js,ico</param-value>
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package app.controllers;
|
||||||
|
|
||||||
|
import org.javalite.activeweb.ControllerSpec;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
|
||||||
|
import app.services.ArticleServiceModule;
|
||||||
|
|
||||||
|
public class ArticleControllerSpec extends ControllerSpec {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
setInjector(Guice.createInjector(new ArticleServiceModule()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenReturnedArticlesThenCorrect() {
|
||||||
|
request().get("index");
|
||||||
|
a(responseContent()).shouldContain("<td>Introduction to Mule</td>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenKeywordWhenFoundArticleThenCorrect() {
|
||||||
|
request().param("key", "Java")
|
||||||
|
.get("search");
|
||||||
|
a(responseContent()).shouldContain("<td>Article with Java</td>");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>microprofile</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<app.name>library</app.name>
|
||||||
|
<package.file>${project.build.directory}/${app.name}-service.jar</package.file>
|
||||||
|
<packaging.type>runnable</packaging.type>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.microprofile</groupId>
|
||||||
|
<artifactId>microprofile</artifactId>
|
||||||
|
<version>1.2</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<type>pom</type>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
|
<packagingExcludes>pom.xml</packagingExcludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.wasdev.wlp.maven.plugins</groupId>
|
||||||
|
<artifactId>liberty-maven-plugin</artifactId>
|
||||||
|
<version>2.1.2</version>
|
||||||
|
<configuration>
|
||||||
|
<assemblyArtifact>
|
||||||
|
<groupId>io.openliberty</groupId>
|
||||||
|
<artifactId>openliberty-runtime</artifactId>
|
||||||
|
<version>17.0.0.4</version>
|
||||||
|
<type>zip</type>
|
||||||
|
</assemblyArtifact>
|
||||||
|
<configFile>${basedir}/src/main/liberty/config/server.xml</configFile>
|
||||||
|
<packageFile>${package.file}</packageFile>
|
||||||
|
<include>${packaging.type}</include>
|
||||||
|
<looseApplication>false</looseApplication>
|
||||||
|
<installAppPackages>project</installAppPackages>
|
||||||
|
<bootstrapProperties>
|
||||||
|
<app.context.root>/</app.context.root>
|
||||||
|
<app.location>${project.artifactId}-${project.version}.war</app.location>
|
||||||
|
<default.http.port>9080</default.http.port>
|
||||||
|
<default.https.port>9443</default.https.port>
|
||||||
|
</bootstrapProperties>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>install-server</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>install-server</goal>
|
||||||
|
<goal>create-server</goal>
|
||||||
|
<goal>install-feature</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>package-server-with-apps</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>install-apps</goal>
|
||||||
|
<goal>package-server</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.microprofile;
|
||||||
|
|
||||||
|
import javax.ws.rs.ApplicationPath;
|
||||||
|
import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
|
@ApplicationPath("/library")
|
||||||
|
public class LibraryApplication extends Application {
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.baeldung.microprofile.model;
|
||||||
|
|
||||||
|
public class Book {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String isbn;
|
||||||
|
private String name;
|
||||||
|
private String author;
|
||||||
|
private Integer pages;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsbn() {
|
||||||
|
return isbn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsbn(String isbn) {
|
||||||
|
this.isbn = isbn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPages() {
|
||||||
|
return pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPages(Integer pages) {
|
||||||
|
this.pages = pages;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.microprofile.providers;
|
||||||
|
|
||||||
|
import com.baeldung.microprofile.model.Book;
|
||||||
|
import com.baeldung.microprofile.util.BookMapper;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonArray;
|
||||||
|
import javax.json.JsonWriter;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.ext.MessageBodyWriter;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Provider
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public class BookListMessageBodyWriter implements MessageBodyWriter<List<Book>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWriteable(Class<?> clazz, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSize(List<Book> books, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(List<Book> books, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
|
||||||
|
JsonWriter jsonWriter = Json.createWriter(entityStream);
|
||||||
|
JsonArray jsonArray = BookMapper.map(books);
|
||||||
|
jsonWriter.writeArray(jsonArray);
|
||||||
|
jsonWriter.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.microprofile.providers;
|
||||||
|
|
||||||
|
import com.baeldung.microprofile.model.Book;
|
||||||
|
import com.baeldung.microprofile.util.BookMapper;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.ext.MessageBodyReader;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
@Provider
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class BookMessageBodyReader implements MessageBodyReader<Book> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||||
|
return type.equals(Book.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Book readFrom(Class<Book> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
|
||||||
|
return BookMapper.map(entityStream);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.baeldung.microprofile.providers;
|
||||||
|
|
||||||
|
import com.baeldung.microprofile.model.Book;
|
||||||
|
import com.baeldung.microprofile.util.BookMapper;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
import javax.json.JsonWriter;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.ext.MessageBodyWriter;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
@Provider
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public class BookMessageBodyWriter implements MessageBodyWriter<Book> {
|
||||||
|
@Override
|
||||||
|
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||||
|
return type.equals(Book.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Deprecated in JAX RS 2.0
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getSize(Book book, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marsahl Book to OutputStream
|
||||||
|
*
|
||||||
|
* @param book
|
||||||
|
* @param type
|
||||||
|
* @param genericType
|
||||||
|
* @param annotations
|
||||||
|
* @param mediaType
|
||||||
|
* @param httpHeaders
|
||||||
|
* @param entityStream
|
||||||
|
* @throws IOException
|
||||||
|
* @throws WebApplicationException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void writeTo(Book book, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
|
||||||
|
JsonWriter jsonWriter = Json.createWriter(entityStream);
|
||||||
|
JsonObject jsonObject = BookMapper.map(book);
|
||||||
|
jsonWriter.writeObject(jsonObject);
|
||||||
|
jsonWriter.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.baeldung.microprofile.repo;
|
||||||
|
|
||||||
|
import com.baeldung.microprofile.model.Book;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class BookManager {
|
||||||
|
|
||||||
|
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
|
||||||
|
private AtomicInteger bookIdGenerator = new AtomicInteger(0);
|
||||||
|
|
||||||
|
private ConcurrentMap<String, Book> inMemoryStore = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public BookManager() {
|
||||||
|
Book book = new Book();
|
||||||
|
book.setId(getNextId());
|
||||||
|
book.setName("Building Microservice With Eclipse MicroProfile");
|
||||||
|
book.setIsbn("1");
|
||||||
|
book.setAuthor("baeldung");
|
||||||
|
book.setPages(420);
|
||||||
|
inMemoryStore.put(book.getId(), book);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNextId() {
|
||||||
|
String date = LocalDate.now().format(formatter);
|
||||||
|
return String.format("%04d-%s", bookIdGenerator.incrementAndGet(), date);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String add(Book book) {
|
||||||
|
String id = getNextId();
|
||||||
|
book.setId(id);
|
||||||
|
inMemoryStore.put(id, book);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Book get(String id) {
|
||||||
|
return inMemoryStore.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Book> getAll() {
|
||||||
|
List<Book> books = new ArrayList<>();
|
||||||
|
books.addAll(inMemoryStore.values());
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.baeldung.microprofile.util;
|
||||||
|
|
||||||
|
import com.baeldung.microprofile.model.Book;
|
||||||
|
|
||||||
|
import javax.json.*;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BookMapper {
|
||||||
|
|
||||||
|
public static JsonObject map(Book book) {
|
||||||
|
JsonObjectBuilder builder = Json.createObjectBuilder();
|
||||||
|
addValue(builder, "id", book.getId());
|
||||||
|
addValue(builder, "isbn", book.getIsbn());
|
||||||
|
addValue(builder, "name", book.getName());
|
||||||
|
addValue(builder, "author", book.getAuthor());
|
||||||
|
addValue(builder, "pages", book.getPages());
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addValue(JsonObjectBuilder builder, String key, Object value) {
|
||||||
|
if (value != null) {
|
||||||
|
builder.add(key, value.toString());
|
||||||
|
} else {
|
||||||
|
builder.addNull(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonArray map(List<Book> books) {
|
||||||
|
final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
|
||||||
|
books.forEach(book -> {
|
||||||
|
JsonObject jsonObject = map(book);
|
||||||
|
arrayBuilder.add(jsonObject);
|
||||||
|
});
|
||||||
|
return arrayBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Book map(InputStream is) {
|
||||||
|
try(JsonReader jsonReader = Json.createReader(is)) {
|
||||||
|
JsonObject jsonObject = jsonReader.readObject();
|
||||||
|
Book book = new Book();
|
||||||
|
book.setId(getStringFromJson("id", jsonObject));
|
||||||
|
book.setIsbn(getStringFromJson("isbn", jsonObject));
|
||||||
|
book.setName(getStringFromJson("name", jsonObject));
|
||||||
|
book.setAuthor(getStringFromJson("author", jsonObject));
|
||||||
|
book.setPages(getIntFromJson("pages",jsonObject));
|
||||||
|
return book;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getStringFromJson(String key, JsonObject json) {
|
||||||
|
String returnedString = null;
|
||||||
|
if (json.containsKey(key)) {
|
||||||
|
JsonString value = json.getJsonString(key);
|
||||||
|
if (value != null) {
|
||||||
|
returnedString = value.getString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnedString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer getIntFromJson(String key, JsonObject json) {
|
||||||
|
Integer returnedValue = null;
|
||||||
|
if (json.containsKey(key)) {
|
||||||
|
JsonNumber value = json.getJsonNumber(key);
|
||||||
|
if (value != null) {
|
||||||
|
returnedValue = value.intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnedValue;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.microprofile.web;
|
||||||
|
|
||||||
|
import com.baeldung.microprofile.model.Book;
|
||||||
|
import com.baeldung.microprofile.repo.BookManager;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.*;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
|
||||||
|
@Path("books")
|
||||||
|
@RequestScoped
|
||||||
|
public class BookEndpoint {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BookManager bookManager;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{id}")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response getBook(@PathParam("id") String id) {
|
||||||
|
Book book = bookManager.get(id);
|
||||||
|
return Response.ok(book).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response getAllBooks() {
|
||||||
|
return Response.ok(bookManager.getAll()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response add(Book book) {
|
||||||
|
String bookId = bookManager.add(book);
|
||||||
|
return Response.created(
|
||||||
|
UriBuilder.fromResource(this.getClass()).path(bookId).build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<server description="OpenLiberty MicroProfile server">
|
||||||
|
<featureManager>
|
||||||
|
<feature>jaxrs-2.0</feature>
|
||||||
|
<feature>cdi-1.2</feature>
|
||||||
|
<feature>jsonp-1.0</feature>
|
||||||
|
</featureManager>
|
||||||
|
<httpEndpoint httpPort="${default.http.port}" httpsPort="${default.https.port}"
|
||||||
|
id="defaultHttpEndpoint" host="*"/>
|
||||||
|
<applicationManager autoExpand="true"/>
|
||||||
|
<webApplication context-root="${app.context.root}" location="${app.location}"/>
|
||||||
|
</server>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue