From 122e6edb38a3a1335363447a8a3f638826a6dab6 Mon Sep 17 00:00:00 2001 From: Noam Greenshtain <31648669+noamgrinch@users.noreply.github.com> Date: Fri, 14 May 2021 18:56:41 +0300 Subject: [PATCH] feature: resolve #1282 for Lockable Object pattern. (#1702) * Added Lockable-Object pattern. Closes #1282. * Refactor method name. * Refactor sonar lint bugs. * Added tests and enum Constants. * Increase coverage. * Changed @Data to Getters and Setters. * Iluwatar's comment on pull request #1702. * Fixed codes mells. * Incremented wait time to 3 seconds. * Reduced wait time to 2 seconds. * Cleaned Code Smells. * Incremented wait time, removed cool down. * Refactored README.md file. Co-authored-by: Subhrodip Mohanta --- lockable-object/README.md | 285 ++++++++++++++++++ lockable-object/etc/lockable-object.urm.png | Bin 0 -> 115658 bytes lockable-object/etc/lockable-object.urm.puml | 94 ++++++ lockable-object/pom.xml | 60 ++++ .../java/com/iluwatar/lockableobject/App.java | 77 +++++ .../com/iluwatar/lockableobject/Lockable.java | 43 +++ .../lockableobject/LockingException.java | 14 + .../lockableobject/SwordOfAragorn.java | 66 ++++ .../lockableobject/domain/Creature.java | 89 ++++++ .../lockableobject/domain/CreatureStats.java | 21 ++ .../lockableobject/domain/CreatureType.java | 8 + .../iluwatar/lockableobject/domain/Elf.java | 17 ++ .../iluwatar/lockableobject/domain/Feind.java | 71 +++++ .../iluwatar/lockableobject/domain/Human.java | 17 ++ .../iluwatar/lockableobject/domain/Orc.java | 16 + .../com/iluwatar/lockableobject/AppTest.java | 41 +++ .../iluwatar/lockableobject/CreatureTest.java | 79 +++++ .../lockableobject/ExceptionsTest.java | 21 ++ .../iluwatar/lockableobject/FeindTest.java | 47 +++ .../lockableobject/SubCreaturesTests.java | 24 ++ .../lockableobject/TheSwordOfAragornTest.java | 27 ++ pom.xml | 1 + 22 files changed, 1118 insertions(+) create mode 100644 lockable-object/README.md create mode 100644 lockable-object/etc/lockable-object.urm.png create mode 100644 lockable-object/etc/lockable-object.urm.puml create mode 100644 lockable-object/pom.xml create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/App.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/Lockable.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/LockingException.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/SwordOfAragorn.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Creature.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureStats.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureType.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Elf.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Feind.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Human.java create mode 100644 lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Orc.java create mode 100644 lockable-object/src/test/java/com/iluwatar/lockableobject/AppTest.java create mode 100644 lockable-object/src/test/java/com/iluwatar/lockableobject/CreatureTest.java create mode 100644 lockable-object/src/test/java/com/iluwatar/lockableobject/ExceptionsTest.java create mode 100644 lockable-object/src/test/java/com/iluwatar/lockableobject/FeindTest.java create mode 100644 lockable-object/src/test/java/com/iluwatar/lockableobject/SubCreaturesTests.java create mode 100644 lockable-object/src/test/java/com/iluwatar/lockableobject/TheSwordOfAragornTest.java diff --git a/lockable-object/README.md b/lockable-object/README.md new file mode 100644 index 000000000..f68ec4336 --- /dev/null +++ b/lockable-object/README.md @@ -0,0 +1,285 @@ +--- +layout: pattern +title: Lockable Object +folder: lockable-object +permalink: /patterns/lockable-object/ +categories: Concurrency +tags: +- Performance +--- + + +## Intent + +The lockable object design pattern ensures that there is only one user using the target object. Compared to the built-in synchronization mechanisms such as using the `synchronized` keyword, this pattern can lock objects for an undetermined time and is not tied to the duration of the request. + +## Explanation + + +Real-world example + +>The Sword Of Aragorn is a legendary object that only one creature can possess at the time. +>Every creature in the middle earth wants to possess is, so as long as it's not locked, every creature will fight for it. + +Under the hood + +>In this particular module, the SwordOfAragorn.java is a class that implements the Lockable interface. +It reaches the goal of the Lockable-Object pattern by implementing unlock() and unlock() methods using +thread-safety logic. The thread-safety logic is implemented with the built-in monitor mechanism of Java. +The SwordOfAaragorn.java has an Object property called "synchronizer". In every crucial concurrency code block, +it's synchronizing the block by using the synchronizer. + + + +**Programmatic Example** + +```java +/** This interface describes the methods to be supported by a lockable object. */ +public interface Lockable { + + /** + * Checks if the object is locked. + * + * @return true if it is locked. + */ + boolean isLocked(); + + /** + * locks the object with the creature as the locker. + * + * @param creature as the locker. + * @return true if the object was locked successfully. + */ + boolean lock(Creature creature); + + /** + * Unlocks the object. + * + * @param creature as the locker. + */ + void unlock(Creature creature); + + /** + * Gets the locker. + * + * @return the Creature that holds the object. Returns null if no one is locking. + */ + Creature getLocker(); + + /** + * Returns the name of the object. + * + * @return the name of the object. + */ + String getName(); +} + +``` + +We have defined that according to our context, the object must implement the Lockable interface. + +For example, the SwordOfAragorn class: + +```java +public class SwordOfAragorn implements Lockable { + + private Creature locker; + private final Object synchronizer; + private static final String NAME = "The Sword of Aragorn"; + + public SwordOfAragorn() { + this.locker = null; + this.synchronizer = new Object(); + } + + @Override + public boolean isLocked() { + return this.locker != null; + } + + @Override + public boolean lock(@NonNull Creature creature) { + synchronized (synchronizer) { + LOGGER.info("{} is now trying to acquire {}!", creature.getName(), this.getName()); + if (!isLocked()) { + locker = creature; + return true; + } else { + if (!locker.getName().equals(creature.getName())) { + return false; + } + } + } + return false; + } + + @Override + public void unlock(@NonNull Creature creature) { + synchronized (synchronizer) { + if (locker != null && locker.getName().equals(creature.getName())) { + locker = null; + LOGGER.info("{} is now free!", this.getName()); + } + if (locker != null) { + throw new LockingException("You cannot unlock an object you are not the owner of."); + } + } + } + + @Override + public Creature getLocker() { + return this.locker; + } + + @Override + public String getName() { + return NAME; + } +} +``` + +According to our context, there are creatures that are looking for the sword, so must define the parent class: + +```java +public abstract class Creature { + + private String name; + private CreatureType type; + private int health; + private int damage; + Set instruments; + + protected Creature(@NonNull String name) { + this.name = name; + this.instruments = new HashSet<>(); + } + + /** + * Reaches for the Lockable and tried to hold it. + * + * @param lockable as the Lockable to lock. + * @return true of Lockable was locked by this creature. + */ + public boolean acquire(@NonNull Lockable lockable) { + if (lockable.lock(this)) { + instruments.add(lockable); + return true; + } + return false; + } + + /** Terminates the Creature and unlocks all of the Lockable that it posses. */ + public synchronized void kill() { + LOGGER.info("{} {} has been slayed!", type, name); + for (Lockable lockable : instruments) { + lockable.unlock(this); + } + this.instruments.clear(); + } + + /** + * Attacks a foe. + * + * @param creature as the foe to be attacked. + */ + public synchronized void attack(@NonNull Creature creature) { + creature.hit(getDamage()); + } + + /** + * When a creature gets hit it removed the amount of damage from the creature's life. + * + * @param damage as the damage that was taken. + */ + public synchronized void hit(int damage) { + if (damage < 0) { + throw new IllegalArgumentException("Damage cannot be a negative number"); + } + if (isAlive()) { + setHealth(getHealth() - damage); + if (!isAlive()) { + kill(); + } + } + } + + /** + * Checks if the creature is still alive. + * + * @return true of creature is alive. + */ + public synchronized boolean isAlive() { + return getHealth() > 0; + } + +} +``` + +As mentioned before, we have classes that extend the Creature class, such as Elf, Orc, and Human. + +Finally, the following program will simulate a battle for the sword: + +```java +public class App implements Runnable { + + private static final int WAIT_TIME = 3; + private static final int WORKERS = 2; + private static final int MULTIPLICATION_FACTOR = 3; + + /** + * main method. + * + * @param args as arguments for the main method. + */ + public static void main(String[] args) { + var app = new App(); + app.run(); + } + + @Override + public void run() { + // The target object for this example. + var sword = new SwordOfAragorn(); + // Creation of creatures. + List creatures = new ArrayList<>(); + for (var i = 0; i < WORKERS; i++) { + creatures.add(new Elf(String.format("Elf %s", i))); + creatures.add(new Orc(String.format("Orc %s", i))); + creatures.add(new Human(String.format("Human %s", i))); + } + int totalFiends = WORKERS * MULTIPLICATION_FACTOR; + ExecutorService service = Executors.newFixedThreadPool(totalFiends); + // Attach every creature and the sword is a Fiend to fight for the sword. + for (var i = 0; i < totalFiends; i = i + MULTIPLICATION_FACTOR) { + service.submit(new Feind(creatures.get(i), sword)); + service.submit(new Feind(creatures.get(i + 1), sword)); + service.submit(new Feind(creatures.get(i + 2), sword)); + } + // Wait for program to terminate. + try { + if (!service.awaitTermination(WAIT_TIME, TimeUnit.SECONDS)) { + LOGGER.info("The master of the sword is now {}.", sword.getLocker().getName()); + } + } catch (InterruptedException e) { + LOGGER.error(e.getMessage()); + Thread.currentThread().interrupt(); + } finally { + service.shutdown(); + } + } +} +``` + +## Applicability + +The Lockable Object pattern is ideal for non distributed applications, that needs to be thread-safe +and keeping their domain models in memory(in contrast to persisted models such as databases). + +## Class diagram + +![alt text](./etc/lockable-object.urm.png "Lockable Object class diagram") + + +## Credits + +* [Lockable Object - Chapter 10.3, J2EE Design Patterns, O'Reilly](http://ommolketab.ir/aaf-lib/axkwht7wxrhvgs2aqkxse8hihyu9zv.pdf) diff --git a/lockable-object/etc/lockable-object.urm.png b/lockable-object/etc/lockable-object.urm.png new file mode 100644 index 0000000000000000000000000000000000000000..431244f2b314b9bb6368f2aa4853d118f0b0297c GIT binary patch literal 115658 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 vVpUrEvRJU + - name : String + - type : CreatureType + + Creature(name : String) + + acquire(lockable : Lockable) : boolean + + attack(creature : Creature) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getDamage() : int + + getHealth() : int + + getInstruments() : Set + + getName() : String + + getType() : CreatureType + + hashCode() : int + + hit(damage : int) + + isAlive() : boolean + + kill() + + setDamage(damage : int) + + setHealth(health : int) + + setInstruments(instruments : Set) + + setName(name : String) + + setType(type : CreatureType) + + toString() : String + } + enum CreatureType { + + ELF {static} + + HUMAN {static} + + ORC {static} + + valueOf(name : String) : CreatureType {static} + + values() : CreatureType[] {static} + } + class Elf { + + Elf(name : String) + } + class Feind { + - LOGGER : Logger {static} + - feind : Creature + - target : Lockable + + Feind(feind : Creature, target : Lockable) + - fightForTheSword(reacher : Creature, holder : Creature, sword : Lockable) + + run() + } + class Human { + + Human(name : String) + } + class Orc { + + Orc(name : String) + } +} +package com.iluwatar.lockableobject { + class App { + - LOGGER : Logger {static} + - MULTIPLICATION_FACTOR : int {static} + - WAIT_TIME : int {static} + - WORKERS : int {static} + + App() + + main(args : String[]) {static} + } + interface Lockable { + + getLocker() : Creature {abstract} + + getName() : String {abstract} + + isLocked() : boolean {abstract} + + lock(Creature) : boolean {abstract} + + unlock(Creature) {abstract} + } + class SwordOfAragorn { + - LOGGER : Logger {static} + - NAME : String {static} + - locker : Creature + - synchronizer : Object + + SwordOfAragorn() + + getLocker() : Creature + + getName() : String + + isLocked() : boolean + + lock(creature : Creature) : boolean + + unlock(creature : Creature) + } +} +Creature --> "-type" CreatureType +Creature --> "-instruments" Lockable +Feind --> "-feind" Creature +Feind --> "-target" Lockable +SwordOfAragorn --> "-locker" Creature +SwordOfAragorn ..|> Lockable +Elf --|> Creature +Human --|> Creature +Orc --|> Creature +@enduml \ No newline at end of file diff --git a/lockable-object/pom.xml b/lockable-object/pom.xml new file mode 100644 index 000000000..a01299dc9 --- /dev/null +++ b/lockable-object/pom.xml @@ -0,0 +1,60 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.25.0-SNAPSHOT + + lockable-object + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.lockableobject.App + + + + + + + + + \ No newline at end of file diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/App.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/App.java new file mode 100644 index 000000000..0429d2494 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/App.java @@ -0,0 +1,77 @@ +package com.iluwatar.lockableobject; + +import com.iluwatar.lockableobject.domain.Creature; +import com.iluwatar.lockableobject.domain.Elf; +import com.iluwatar.lockableobject.domain.Feind; +import com.iluwatar.lockableobject.domain.Human; +import com.iluwatar.lockableobject.domain.Orc; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; + +/** + * The Lockable Object pattern is a concurrency pattern. Instead of using the "synchronized" word + * upon the methods to be synchronized, the object which implements the Lockable interface handles + * the request. + * + *

In this example, we create a new Lockable object with the SwordOfAragorn implementation of it. + * Afterwards we create 6 Creatures with the Elf, Orc and Human implementations and assign them each + * to a Fiend object and the Sword is the target object. Because there is only one Sword and it uses + * the Lockable Object pattern, only one creature can hold the sword at a given time. When the sword + * is locked, any other alive Fiends will try to lock, which will result in a race to lock the + * sword. + * + * @author Noam Greenshtain + */ +@Slf4j +public class App implements Runnable { + + private static final int WAIT_TIME = 3; + private static final int WORKERS = 2; + private static final int MULTIPLICATION_FACTOR = 3; + + /** + * main method. + * + * @param args as arguments for the main method. + */ + public static void main(String[] args) { + var app = new App(); + app.run(); + } + + @Override + public void run() { + // The target object for this example. + var sword = new SwordOfAragorn(); + // Creation of creatures. + List creatures = new ArrayList<>(); + for (var i = 0; i < WORKERS; i++) { + creatures.add(new Elf(String.format("Elf %s", i))); + creatures.add(new Orc(String.format("Orc %s", i))); + creatures.add(new Human(String.format("Human %s", i))); + } + int totalFiends = WORKERS * MULTIPLICATION_FACTOR; + ExecutorService service = Executors.newFixedThreadPool(totalFiends); + // Attach every creature and the sword is a Fiend to fight for the sword. + for (var i = 0; i < totalFiends; i = i + MULTIPLICATION_FACTOR) { + service.submit(new Feind(creatures.get(i), sword)); + service.submit(new Feind(creatures.get(i + 1), sword)); + service.submit(new Feind(creatures.get(i + 2), sword)); + } + // Wait for program to terminate. + try { + if (!service.awaitTermination(WAIT_TIME, TimeUnit.SECONDS)) { + LOGGER.info("The master of the sword is now {}.", sword.getLocker().getName()); + } + } catch (InterruptedException e) { + LOGGER.error(e.getMessage()); + Thread.currentThread().interrupt(); + } finally { + service.shutdown(); + } + } +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/Lockable.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/Lockable.java new file mode 100644 index 000000000..b0257236b --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/Lockable.java @@ -0,0 +1,43 @@ +package com.iluwatar.lockableobject; + +import com.iluwatar.lockableobject.domain.Creature; + +/** This interface describes the methods to be supported by a lockable-object. */ +public interface Lockable { + + /** + * Checks if the object is locked. + * + * @return true if it is locked. + */ + boolean isLocked(); + + /** + * locks the object with the creature as the locker. + * + * @param creature as the locker. + * @return true if the object was locked successfully. + */ + boolean lock(Creature creature); + + /** + * Unlocks the object. + * + * @param creature as the locker. + */ + void unlock(Creature creature); + + /** + * Gets the locker. + * + * @return the Creature that holds the object. Returns null if no one is locking. + */ + Creature getLocker(); + + /** + * Returns the name of the object. + * + * @return the name of the object. + */ + String getName(); +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/LockingException.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/LockingException.java new file mode 100644 index 000000000..2446ce6b0 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/LockingException.java @@ -0,0 +1,14 @@ +package com.iluwatar.lockableobject; + +/** + * An exception regarding the locking process of a Lockable object. + */ +public class LockingException extends RuntimeException { + + private static final long serialVersionUID = 8556381044865867037L; + + public LockingException(String message) { + super(message); + } + +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/SwordOfAragorn.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/SwordOfAragorn.java new file mode 100644 index 000000000..1840c3770 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/SwordOfAragorn.java @@ -0,0 +1,66 @@ +package com.iluwatar.lockableobject; + +import com.iluwatar.lockableobject.domain.Creature; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +/** + * An implementation of a Lockable object. This is the the Sword of Aragorn and every creature wants + * to posses it! + */ +@Slf4j +public class SwordOfAragorn implements Lockable { + + private Creature locker; + private final Object synchronizer; + private static final String NAME = "The Sword of Aragorn"; + + public SwordOfAragorn() { + this.locker = null; + this.synchronizer = new Object(); + } + + @Override + public boolean isLocked() { + return this.locker != null; + } + + @Override + public boolean lock(@NonNull Creature creature) { + synchronized (synchronizer) { + LOGGER.info("{} is now trying to acquire {}!", creature.getName(), this.getName()); + if (!isLocked()) { + locker = creature; + return true; + } else { + if (!locker.getName().equals(creature.getName())) { + return false; + } + } + } + return false; + } + + @Override + public void unlock(@NonNull Creature creature) { + synchronized (synchronizer) { + if (locker != null && locker.getName().equals(creature.getName())) { + locker = null; + LOGGER.info("{} is now free!", this.getName()); + } + if (locker != null) { + throw new LockingException("You cannot unlock an object you are not the owner of."); + } + } + } + + @Override + public Creature getLocker() { + return this.locker; + } + + @Override + public String getName() { + return NAME; + } +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Creature.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Creature.java new file mode 100644 index 000000000..736fd0e98 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Creature.java @@ -0,0 +1,89 @@ +package com.iluwatar.lockableobject.domain; + +import com.iluwatar.lockableobject.Lockable; +import java.util.HashSet; +import java.util.Set; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +/** + * An abstract class of a creature that wanders across the wasteland. It can attack, get hit and + * acquire a Lockable object. + */ +@Getter +@Setter +@Slf4j +public abstract class Creature { + + private String name; + private CreatureType type; + private int health; + private int damage; + Set instruments; + + protected Creature(@NonNull String name) { + this.name = name; + this.instruments = new HashSet<>(); + } + + /** + * Reaches for the Lockable and tried to hold it. + * + * @param lockable as the Lockable to lock. + * @return true of Lockable was locked by this creature. + */ + public boolean acquire(@NonNull Lockable lockable) { + if (lockable.lock(this)) { + instruments.add(lockable); + return true; + } + return false; + } + + /** Terminates the Creature and unlocks all of the Lockable that it posses. */ + public synchronized void kill() { + LOGGER.info("{} {} has been slayed!", type, name); + for (Lockable lockable : instruments) { + lockable.unlock(this); + } + this.instruments.clear(); + } + + /** + * Attacks a foe. + * + * @param creature as the foe to be attacked. + */ + public synchronized void attack(@NonNull Creature creature) { + creature.hit(getDamage()); + } + + /** + * When a creature gets hit it removed the amount of damage from the creature's life. + * + * @param damage as the damage that was taken. + */ + public synchronized void hit(int damage) { + if (damage < 0) { + throw new IllegalArgumentException("Damage cannot be a negative number"); + } + if (isAlive()) { + setHealth(getHealth() - damage); + if (!isAlive()) { + kill(); + } + } + } + + /** + * Checks if the creature is still alive. + * + * @return true of creature is alive. + */ + public synchronized boolean isAlive() { + return getHealth() > 0; + } + +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureStats.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureStats.java new file mode 100644 index 000000000..dac74bd36 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureStats.java @@ -0,0 +1,21 @@ +package com.iluwatar.lockableobject.domain; + +/** Attribute constants of each Creature implementation. */ +public enum CreatureStats { + ELF_HEALTH(90), + ELF_DAMAGE(40), + ORC_HEALTH(70), + ORC_DAMAGE(50), + HUMAN_HEALTH(60), + HUMAN_DAMAGE(60); + + int value; + + private CreatureStats(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureType.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureType.java new file mode 100644 index 000000000..5bb0734b1 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureType.java @@ -0,0 +1,8 @@ +package com.iluwatar.lockableobject.domain; + +/** Constants of supported creatures. */ +public enum CreatureType { + ORC, + HUMAN, + ELF +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Elf.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Elf.java new file mode 100644 index 000000000..56b22ec67 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Elf.java @@ -0,0 +1,17 @@ +package com.iluwatar.lockableobject.domain; + +/** An Elf implementation of a Creature. */ +public class Elf extends Creature { + + /** + * A constructor that initializes the attributes of an elf. + * + * @param name as the name of the creature. + */ + public Elf(String name) { + super(name); + setType(CreatureType.ELF); + setDamage(CreatureStats.ELF_DAMAGE.getValue()); + setHealth(CreatureStats.ELF_HEALTH.getValue()); + } +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Feind.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Feind.java new file mode 100644 index 000000000..cf793b520 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Feind.java @@ -0,0 +1,71 @@ +package com.iluwatar.lockableobject.domain; + +import com.iluwatar.lockableobject.Lockable; +import java.security.SecureRandom; +import lombok.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** A Feind is a creature that all it wants is to posses a Lockable object. */ +public class Feind implements Runnable { + + private final Creature creature; + private final Lockable target; + private final SecureRandom random; + private static final Logger LOGGER = LoggerFactory.getLogger(Feind.class.getName()); + + /** + * public constructor. + * + * @param feind as the creature to lock to he lockable. + * @param target as the target object. + */ + public Feind(@NonNull Creature feind, @NonNull Lockable target) { + this.creature = feind; + this.target = target; + this.random = new SecureRandom(); + } + + @Override + public void run() { + if (!creature.acquire(target)) { + try { + fightForTheSword(creature, target.getLocker(), target); + } catch (InterruptedException e) { + LOGGER.error(e.getMessage()); + Thread.currentThread().interrupt(); + } + } else { + LOGGER.info("{} has acquired the sword!", target.getLocker().getName()); + } + } + + /** + * Keeps on fighting until the Lockable is possessed. + * + * @param reacher as the source creature. + * @param holder as the foe. + * @param sword as the Lockable to posses. + * @throws InterruptedException in case of interruption. + */ + private void fightForTheSword(Creature reacher, @NonNull Creature holder, Lockable sword) + throws InterruptedException { + LOGGER.info("A duel between {} and {} has been started!", reacher.getName(), holder.getName()); + boolean randBool; + while (this.target.isLocked() && reacher.isAlive() && holder.isAlive()) { + randBool = random.nextBoolean(); + if (randBool) { + reacher.attack(holder); + } else { + holder.attack(reacher); + } + } + if (reacher.isAlive()) { + if (!reacher.acquire(sword)) { + fightForTheSword(reacher, sword.getLocker(), sword); + } else { + LOGGER.info("{} has acquired the sword!", reacher.getName()); + } + } + } +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Human.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Human.java new file mode 100644 index 000000000..6ff3c8bad --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Human.java @@ -0,0 +1,17 @@ +package com.iluwatar.lockableobject.domain; + +/** A human implementation of a Creature. */ +public class Human extends Creature { + + /** + * A constructor that initializes the attributes of an human. + * + * @param name as the name of the creature. + */ + public Human(String name) { + super(name); + setType(CreatureType.HUMAN); + setDamage(CreatureStats.HUMAN_DAMAGE.getValue()); + setHealth(CreatureStats.HUMAN_HEALTH.getValue()); + } +} diff --git a/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Orc.java b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Orc.java new file mode 100644 index 000000000..a74637a44 --- /dev/null +++ b/lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Orc.java @@ -0,0 +1,16 @@ +package com.iluwatar.lockableobject.domain; + +/** A Orc implementation of a Creature. */ +public class Orc extends Creature { + /** + * A constructor that initializes the attributes of an orc. + * + * @param name as the name of the creature. + */ + public Orc(String name) { + super(name); + setType(CreatureType.ORC); + setDamage(CreatureStats.ORC_DAMAGE.getValue()); + setHealth(CreatureStats.ORC_HEALTH.getValue()); + } +} diff --git a/lockable-object/src/test/java/com/iluwatar/lockableobject/AppTest.java b/lockable-object/src/test/java/com/iluwatar/lockableobject/AppTest.java new file mode 100644 index 000000000..8198d3bee --- /dev/null +++ b/lockable-object/src/test/java/com/iluwatar/lockableobject/AppTest.java @@ -0,0 +1,41 @@ +/* + * The MIT License + * Copyright © 2014-2021 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.lockableobject; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.Test; + +class AppTest { + + @Test + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[] {})); + } + + @Test + void shouldExecuteApplicationAsRunnableWithoutException() { + assertDoesNotThrow(() -> (new App()).run()); + } +} diff --git a/lockable-object/src/test/java/com/iluwatar/lockableobject/CreatureTest.java b/lockable-object/src/test/java/com/iluwatar/lockableobject/CreatureTest.java new file mode 100644 index 000000000..9986e1951 --- /dev/null +++ b/lockable-object/src/test/java/com/iluwatar/lockableobject/CreatureTest.java @@ -0,0 +1,79 @@ +package com.iluwatar.lockableobject; + +import com.iluwatar.lockableobject.domain.Creature; +import com.iluwatar.lockableobject.domain.CreatureStats; +import com.iluwatar.lockableobject.domain.CreatureType; +import com.iluwatar.lockableobject.domain.Elf; +import com.iluwatar.lockableobject.domain.Orc; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class CreatureTest { + + private Creature orc; + private Creature elf; + private Lockable sword; + + @BeforeEach + void init() { + elf = new Elf("Elf test"); + orc = new Orc("Orc test"); + sword = new SwordOfAragorn(); + } + + @Test + void baseTest() { + Assertions.assertEquals("Elf test", elf.getName()); + Assertions.assertEquals(CreatureType.ELF, elf.getType()); + Assertions.assertThrows(NullPointerException.class, () -> new Elf(null)); + Assertions.assertThrows(NullPointerException.class, () -> elf.acquire(null)); + Assertions.assertThrows(NullPointerException.class, () -> elf.attack(null)); + Assertions.assertThrows(IllegalArgumentException.class, () -> elf.hit(-10)); + } + + @Test + void hitTest() { + elf.hit(CreatureStats.ELF_HEALTH.getValue() / 2); + Assertions.assertEquals(CreatureStats.ELF_HEALTH.getValue() / 2, elf.getHealth()); + elf.hit(CreatureStats.ELF_HEALTH.getValue() / 2); + Assertions.assertFalse(elf.isAlive()); + + Assertions.assertEquals(0, orc.getInstruments().size()); + Assertions.assertTrue(orc.acquire(sword)); + Assertions.assertEquals(1, orc.getInstruments().size()); + orc.kill(); + Assertions.assertEquals(0, orc.getInstruments().size()); + } + + @Test + void testFight() throws InterruptedException { + killCreature(elf, orc); + Assertions.assertTrue(elf.isAlive()); + Assertions.assertFalse(orc.isAlive()); + Assertions.assertTrue(elf.getHealth() > 0); + Assertions.assertTrue(orc.getHealth() <= 0); + } + + @Test + void testAcqusition() throws InterruptedException { + Assertions.assertTrue(elf.acquire(sword)); + Assertions.assertEquals(elf.getName(), sword.getLocker().getName()); + Assertions.assertTrue(elf.getInstruments().contains(sword)); + Assertions.assertFalse(orc.acquire(sword)); + killCreature(orc, elf); + Assertions.assertTrue(orc.acquire(sword)); + Assertions.assertEquals(orc, sword.getLocker()); + } + + void killCreature(Creature source, Creature target) throws InterruptedException { + while (target.isAlive()) { + source.attack(target); + } + } + + @Test + void invalidDamageTest(){ + Assertions.assertThrows(IllegalArgumentException.class, () -> elf.hit(-50)); + } +} diff --git a/lockable-object/src/test/java/com/iluwatar/lockableobject/ExceptionsTest.java b/lockable-object/src/test/java/com/iluwatar/lockableobject/ExceptionsTest.java new file mode 100644 index 000000000..bb6d7a9dc --- /dev/null +++ b/lockable-object/src/test/java/com/iluwatar/lockableobject/ExceptionsTest.java @@ -0,0 +1,21 @@ +package com.iluwatar.lockableobject; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ExceptionsTest { + + private String msg = "test"; + + @Test + void testException(){ + Exception e; + try{ + throw new LockingException(msg); + } + catch(LockingException ex){ + e = ex; + } + Assertions.assertEquals(msg, e.getMessage()); + } +} diff --git a/lockable-object/src/test/java/com/iluwatar/lockableobject/FeindTest.java b/lockable-object/src/test/java/com/iluwatar/lockableobject/FeindTest.java new file mode 100644 index 000000000..230ffbccb --- /dev/null +++ b/lockable-object/src/test/java/com/iluwatar/lockableobject/FeindTest.java @@ -0,0 +1,47 @@ +package com.iluwatar.lockableobject; + +import com.iluwatar.lockableobject.domain.Creature; +import com.iluwatar.lockableobject.domain.Elf; +import com.iluwatar.lockableobject.domain.Feind; +import com.iluwatar.lockableobject.domain.Orc; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class FeindTest { + + private Creature elf; + private Creature orc; + private Lockable sword; + + @BeforeEach + void init(){ + elf = new Elf("Nagdil"); + orc = new Orc("Ghandar"); + sword = new SwordOfAragorn(); + } + + @Test + void nullTests(){ + Assertions.assertThrows(NullPointerException.class, () -> new Feind(null, null)); + Assertions.assertThrows(NullPointerException.class, () -> new Feind(elf, null)); + Assertions.assertThrows(NullPointerException.class, () -> new Feind(null, sword)); + } + + @Test + void testBaseCase() throws InterruptedException { + var base = new Thread(new Feind(orc, sword)); + Assertions.assertNull(sword.getLocker()); + base.start(); + base.join(); + Assertions.assertEquals(orc, sword.getLocker()); + var extend = new Thread(new Feind(elf, sword)); + extend.start(); + extend.join(); + Assertions.assertTrue(sword.isLocked()); + + sword.unlock(elf.isAlive() ? elf : orc); + Assertions.assertNull(sword.getLocker()); + } + +} diff --git a/lockable-object/src/test/java/com/iluwatar/lockableobject/SubCreaturesTests.java b/lockable-object/src/test/java/com/iluwatar/lockableobject/SubCreaturesTests.java new file mode 100644 index 000000000..72cedbc43 --- /dev/null +++ b/lockable-object/src/test/java/com/iluwatar/lockableobject/SubCreaturesTests.java @@ -0,0 +1,24 @@ +package com.iluwatar.lockableobject; + +import com.iluwatar.lockableobject.domain.CreatureStats; +import com.iluwatar.lockableobject.domain.Elf; +import com.iluwatar.lockableobject.domain.Human; +import com.iluwatar.lockableobject.domain.Orc; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class SubCreaturesTests { + + @Test + void statsTest(){ + var elf = new Elf("Limbar"); + var orc = new Orc("Dargal"); + var human = new Human("Jerry"); + Assertions.assertEquals(CreatureStats.ELF_HEALTH.getValue(), elf.getHealth()); + Assertions.assertEquals(CreatureStats.ELF_DAMAGE.getValue(), elf.getDamage()); + Assertions.assertEquals(CreatureStats.ORC_DAMAGE.getValue(), orc.getDamage()); + Assertions.assertEquals(CreatureStats.ORC_HEALTH.getValue(), orc.getHealth()); + Assertions.assertEquals(CreatureStats.HUMAN_DAMAGE.getValue(), human.getDamage()); + Assertions.assertEquals(CreatureStats.HUMAN_HEALTH.getValue(), human.getHealth()); + } +} diff --git a/lockable-object/src/test/java/com/iluwatar/lockableobject/TheSwordOfAragornTest.java b/lockable-object/src/test/java/com/iluwatar/lockableobject/TheSwordOfAragornTest.java new file mode 100644 index 000000000..186e085ea --- /dev/null +++ b/lockable-object/src/test/java/com/iluwatar/lockableobject/TheSwordOfAragornTest.java @@ -0,0 +1,27 @@ +package com.iluwatar.lockableobject; + +import com.iluwatar.lockableobject.domain.Human; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class TheSwordOfAragornTest { + + @Test + void basicSwordTest() { + var sword = new SwordOfAragorn(); + Assertions.assertNotNull(sword.getName()); + Assertions.assertNull(sword.getLocker()); + Assertions.assertFalse(sword.isLocked()); + var human = new Human("Tupac"); + Assertions.assertTrue(human.acquire(sword)); + Assertions.assertEquals(human, sword.getLocker()); + Assertions.assertTrue(sword.isLocked()); + } + + @Test + void invalidLockerTest(){ + var sword = new SwordOfAragorn(); + Assertions.assertThrows(NullPointerException.class, () -> sword.lock(null)); + Assertions.assertThrows(NullPointerException.class, () -> sword.unlock(null)); + } +} diff --git a/pom.xml b/pom.xml index 9cd6b6adb..1b8f30e92 100644 --- a/pom.xml +++ b/pom.xml @@ -226,6 +226,7 @@ model-view-viewmodel composite-entity presentation + lockable-object