diff --git a/FiniteStateMachine/etc/FiniteStateMachine.urm.puml b/FiniteStateMachine/etc/FiniteStateMachine.urm.puml new file mode 100644 index 000000000000..d665b26a8900 --- /dev/null +++ b/FiniteStateMachine/etc/FiniteStateMachine.urm.puml @@ -0,0 +1,34 @@ +@startuml +package com.iluwatar.trafficlight { + class GreenLightState { + + GreenLightState() + + handleEvent(context : TrafficLightContext) + } + class RedLightState { + + RedLightState() + + handleEvent(context : TrafficLightContext) + } + class TrafficLightContext { + - currentState : TrafficLightState + + TrafficLightContext(initialState : TrafficLightState) + + getCurrentState() : TrafficLightState + + handleEvent() + + setState(newState : TrafficLightState) + } + class TrafficLightFsm { + + TrafficLightFsm() + + main(args : String[]) {static} + } + interface TrafficLightState { + + handleEvent(TrafficLightContext) {abstract} + } + class YellowLightState { + + YellowLightState() + + handleEvent(context : TrafficLightContext) + } +} +TrafficLightContext --> "-currentState" TrafficLightState +GreenLightState ..|> TrafficLightState +RedLightState ..|> TrafficLightState +YellowLightState ..|> TrafficLightState +@enduml \ No newline at end of file diff --git a/FiniteStateMachine/pom.xml b/FiniteStateMachine/pom.xml new file mode 100644 index 000000000000..59f8ab32f006 --- /dev/null +++ b/FiniteStateMachine/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + + FiniteStateMachine + + + 17 + 17 + UTF-8 + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.mockito + mockito-core + test + + + + \ No newline at end of file diff --git a/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/GreenLightState.java b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/GreenLightState.java new file mode 100644 index 000000000000..29573fa20253 --- /dev/null +++ b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/GreenLightState.java @@ -0,0 +1,23 @@ +package com.iluwatar.trafficlight; + +/** + * Concrete state representing the Green Light. + */ +public class GreenLightState implements TrafficLightState { + + /** + * Handles the event for the Green Light. + * This method transitions the traffic light to the Yellow state after the Green state. + * + * @param context The traffic light context to manage the state transitions. + */ + @Override + public void handleEvent(TrafficLightContext context) { + System.out.println("Green Light: Go!"); + // Transition to the Yellow light state + context.setState(new YellowLightState()); + } +} + + + diff --git a/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/RedLightState.java b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/RedLightState.java new file mode 100644 index 000000000000..c7514b468555 --- /dev/null +++ b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/RedLightState.java @@ -0,0 +1,14 @@ +package com.iluwatar.trafficlight; + +/** + * Concrete state representing the Red Light. + */ +public class RedLightState implements TrafficLightState { + @Override + public void handleEvent(TrafficLightContext context) { + System.out.println("Red Light: Stop!"); + context.setState(new GreenLightState()); + } +} + + diff --git a/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightContext.java b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightContext.java new file mode 100644 index 000000000000..fe5361ab1357 --- /dev/null +++ b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightContext.java @@ -0,0 +1,43 @@ +package com.iluwatar.trafficlight; + +/** + * Context class for managing the current state and transitions. + */ +public class TrafficLightContext { + private TrafficLightState currentState; + + /** + * Initializes the context with the given initial state. + * + * @param initialState the initial state of the traffic light + */ + public TrafficLightContext(TrafficLightState initialState) { + this.currentState = initialState; + } + + /** + * Updates the current state of the traffic light. + * + * @param newState the new state to transition to + */ + public void setState(TrafficLightState newState) { + this.currentState = newState; + } + + /** + * Handles the current state's event and transitions to the next state. + */ + public void handleEvent() { + currentState.handleEvent(this); + } + + /** + * Gets the current state of the traffic light. + * This can be useful for testing purposes. + */ + public TrafficLightState getCurrentState() { + return currentState; + } +} + + diff --git a/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightFsm.java b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightFsm.java new file mode 100644 index 000000000000..9c3dd0c6d7d0 --- /dev/null +++ b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightFsm.java @@ -0,0 +1,27 @@ +package com.iluwatar.trafficlight; + +/** + * Simulates a traffic light system using a Finite State Machine (FSM). + */ +public class TrafficLightFsm { + + /** + * Runs the traffic light simulation. + * + * @param args command-line arguments (not used here) + */ + public static void main(String[] args) { + // Start with the Red light + TrafficLightContext trafficLight = new TrafficLightContext(new RedLightState()); + + // Cycle through the traffic light states + for (int i = 0; i < 6; i++) { + trafficLight.handleEvent(); + } + } +} + + + + + diff --git a/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightState.java b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightState.java new file mode 100644 index 000000000000..bb06e45a2453 --- /dev/null +++ b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightState.java @@ -0,0 +1,19 @@ +package com.iluwatar.trafficlight; + +/** + * State interface for traffic light states. + */ +public interface TrafficLightState { + + /** + * Handles the transition to the next state based on the current state. + * + * @param context the context object that manages the traffic light's state + */ + void handleEvent(TrafficLightContext context); +} + + + + + diff --git a/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/YellowLightState.java b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/YellowLightState.java new file mode 100644 index 000000000000..07306f600ee9 --- /dev/null +++ b/FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/YellowLightState.java @@ -0,0 +1,13 @@ +package com.iluwatar.trafficlight; + +/** + * Concrete state representing the Yellow Light. + */ +public class YellowLightState implements TrafficLightState { + @Override + public void handleEvent(TrafficLightContext context) { + System.out.println("Yellow Light: Caution!"); + context.setState(new RedLightState()); + } +} + diff --git a/FiniteStateMachine/src/test/java/com/iluwater/TrafficLightTest.java b/FiniteStateMachine/src/test/java/com/iluwater/TrafficLightTest.java new file mode 100644 index 000000000000..4f2d3d3253a5 --- /dev/null +++ b/FiniteStateMachine/src/test/java/com/iluwater/TrafficLightTest.java @@ -0,0 +1,176 @@ +package com.iluwater; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.iluwatar.trafficlight.GreenLightState; +import com.iluwatar.trafficlight.RedLightState; +import com.iluwatar.trafficlight.TrafficLightContext; +import com.iluwatar.trafficlight.TrafficLightFsm; +import com.iluwatar.trafficlight.YellowLightState; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Test class for the Traffic Light FSM. + */ +public class TrafficLightTest { + + private TrafficLightContext context; + + @BeforeEach + void setUp() { + // Start with the Red Light state + context = new TrafficLightContext(new RedLightState()); + } + + @Test + void testInitialState() { + assertTrue(context.getCurrentState() instanceof RedLightState, "Initial state should be RedLightState."); + } + + @Test + void testRedToGreenTransition() { + context.handleEvent(); + assertTrue(context.getCurrentState() instanceof GreenLightState, "Red Light should transition to Green Light."); + } + + @Test + void testGreenToYellowTransition() { + context.setState(new GreenLightState()); + context.handleEvent(); + assertTrue(context.getCurrentState() instanceof YellowLightState, "Green Light should transition to Yellow Light."); + } + + @Test + void testYellowToRedTransition() { + context.setState(new YellowLightState()); + context.handleEvent(); + assertTrue(context.getCurrentState() instanceof RedLightState, "Yellow Light should transition to Red Light."); + } + + @Test + void testFullCycle() { + context.handleEvent(); // Red -> Green + assertTrue(context.getCurrentState() instanceof GreenLightState); + + context.handleEvent(); // Green -> Yellow + assertTrue(context.getCurrentState() instanceof YellowLightState); + + context.handleEvent(); // Yellow -> Red + assertTrue(context.getCurrentState() instanceof RedLightState); + } + + // Test invalid state transition + @Test + void testInvalidStateTransition() { + context.setState(new RedLightState()); + try { + // This should fail, as it doesn't make sense for Red to handle an event again. + context.handleEvent(); + } catch (IllegalStateException e) { + assertTrue(true, "Handled invalid state transition."); + } + } + + // Test state reset + @Test + void testStateReset() { + context.setState(new YellowLightState()); + context.handleEvent(); // Yellow -> Red + assertTrue(context.getCurrentState() instanceof RedLightState); + + context.setState(new GreenLightState()); + context.handleEvent(); // Green -> Yellow + assertTrue(context.getCurrentState() instanceof YellowLightState); + + context.setState(new RedLightState()); + context.handleEvent(); // Red -> Green + assertTrue(context.getCurrentState() instanceof GreenLightState); + } + + // Test manually setting the state + @Test + void testManualStateSet() { + context.setState(new GreenLightState()); + assertTrue(context.getCurrentState() instanceof GreenLightState); + + context.setState(new YellowLightState()); + assertTrue(context.getCurrentState() instanceof YellowLightState); + + context.setState(new RedLightState()); + assertTrue(context.getCurrentState() instanceof RedLightState); + } + + // Additional tests for edge cases + + // Test if state is correctly set in the middle of a cycle + @Test + void testMidCycleStateSet() { + context.handleEvent(); // Red -> Green + assertTrue(context.getCurrentState() instanceof GreenLightState); + + // Set state manually in the middle of the cycle + context.setState(new YellowLightState()); + assertTrue(context.getCurrentState() instanceof YellowLightState); + + context.handleEvent(); // Yellow -> Red + assertTrue(context.getCurrentState() instanceof RedLightState); + } + + // Test if context properly resets after complete cycle + @Test + void testContextResetAfterFullCycle() { + context.handleEvent(); // Red -> Green + context.handleEvent(); // Green -> Yellow + context.handleEvent(); // Yellow -> Red + + // Reset and verify again + context.setState(new GreenLightState()); + assertTrue(context.getCurrentState() instanceof GreenLightState); + + context.handleEvent(); // Green -> Yellow + assertTrue(context.getCurrentState() instanceof YellowLightState); + + context.handleEvent(); // Yellow -> Red + assertTrue(context.getCurrentState() instanceof RedLightState); + } + + // Test if the initial state remains unchanged after multiple cycles + @Test + void testMultipleCycles() { + context.handleEvent(); // Red -> Green + context.handleEvent(); // Green -> Yellow + context.handleEvent(); // Yellow -> Red + + // Perform another full cycle and ensure the state remains correct + context.handleEvent(); // Red -> Green + assertTrue(context.getCurrentState() instanceof GreenLightState); + + context.handleEvent(); // Green -> Yellow + assertTrue(context.getCurrentState() instanceof YellowLightState); + + context.handleEvent(); // Yellow -> Red + assertTrue(context.getCurrentState() instanceof RedLightState); + } + + // Test if state changes properly when reset in the middle of cycles + @Test + void testResetMidCycle() { + context.handleEvent(); // Red -> Green + context.setState(new YellowLightState()); // Manually set Yellow + assertTrue(context.getCurrentState() instanceof YellowLightState); + context.handleEvent(); // Yellow -> Red + assertTrue(context.getCurrentState() instanceof RedLightState); + } + + // Test for traffic light FSM running through multiple cycles + @Test + void testTrafficLightFsmCycles() { + // Start the FSM and cycle through multiple events + TrafficLightFsm.main(new String[0]); // This will run the logic in the main function of TrafficLightFsm + } +} + + + + diff --git a/fluent-interface/etc/fluent-interface.urm.puml b/fluent-interface/etc/fluent-interface.urm.puml new file mode 100644 index 000000000000..d343a478bff0 --- /dev/null +++ b/fluent-interface/etc/fluent-interface.urm.puml @@ -0,0 +1,72 @@ +@startuml +package com.iluwatar.fluentinterface.fluentiterable.simple { + class SimpleFluentIterable { + - iterable : Iterable + + SimpleFluentIterable(iterable : Iterable) + + asList() : List + + filter(predicate : Predicate) : FluentIterable + + first() : Optional + + first(count : int) : FluentIterable + + forEach(action : Consumer) + + from(iterable : Iterable) : FluentIterable {static} + + fromCopyOf(iterable : Iterable) : FluentIterable {static} + + getRemainingElementsCount() : int + + iterator() : Iterator + + last() : Optional + + last(count : int) : FluentIterable + + map(function : Function) : FluentIterable + + spliterator() : Spliterator + + toList(iterator : Iterator) : List {static} + } +} +package com.iluwatar.fluentinterface.app { + class App { + - LOGGER : Logger {static} + + App() + + main(args : String[]) {static} + - negatives() : Predicate {static} + - positives() : Predicate {static} + - prettyPrint(delimiter : String, prefix : String, iterable : Iterable) {static} + - prettyPrint(prefix : String, iterable : Iterable) {static} + - transformToString() : Function {static} + } +} +package com.iluwatar.fluentinterface.fluentiterable.lazy { + abstract class DecoratingIterator { + # fromIterator : Iterator + - next : E + + DecoratingIterator(fromIterator : Iterator) + + computeNext() : E {abstract} + + hasNext() : boolean + + next() : E + } + class LazyFluentIterable { + - iterable : Iterable + # LazyFluentIterable() + + LazyFluentIterable(iterable : Iterable) + + asList() : List + + filter(predicate : Predicate) : FluentIterable + + first() : Optional + + first(count : int) : FluentIterable + + from(iterable : Iterable) : FluentIterable {static} + + iterator() : Iterator + + last() : Optional + + last(count : int) : FluentIterable + + map(function : Function) : FluentIterable + } +} +package com.iluwatar.fluentinterface.fluentiterable { + interface FluentIterable { + + asList() : List {abstract} + + copyToList(iterable : Iterable) : List {static} + + filter(Predicate) : FluentIterable {abstract} + + first() : Optional {abstract} + + first(int) : FluentIterable {abstract} + + last() : Optional {abstract} + + last(int) : FluentIterable {abstract} + + map(Function) : FluentIterable {abstract} + } +} +LazyFluentIterable ..|> FluentIterable +SimpleFluentIterable ..|> FluentIterable +@enduml \ No newline at end of file diff --git a/function-composition/etc/function-composition.urm.puml b/function-composition/etc/function-composition.urm.puml new file mode 100644 index 000000000000..79b2a898fd12 --- /dev/null +++ b/function-composition/etc/function-composition.urm.puml @@ -0,0 +1,12 @@ +@startuml +package com.iluwatar.function.composition { + class App { + + App() + + main(args : String[]) {static} + } + class FunctionComposer { + + FunctionComposer() + + composeFunctions(f1 : Function, f2 : Function) : Function {static} + } +} +@enduml \ No newline at end of file diff --git a/hexagonal-architecture/etc/hexagonal-architecture.urm.puml b/hexagonal-architecture/etc/hexagonal-architecture.urm.puml new file mode 100644 index 000000000000..f86e734747f3 --- /dev/null +++ b/hexagonal-architecture/etc/hexagonal-architecture.urm.puml @@ -0,0 +1,282 @@ +@startuml +package com.iluwatar.hexagonal.sampledata { + class SampleData { + - PLAYERS : List {static} + - RANDOM : SecureRandom {static} + + SampleData() + - getRandomPlayerDetails() : PlayerDetails {static} + + submitTickets(lotteryService : LotteryService, numTickets : int) {static} + } +} +package com.iluwatar.hexagonal.service { + class ConsoleLottery { + - LOGGER : Logger {static} + + ConsoleLottery() + + main(args : String[]) {static} + - printMainMenu() {static} + - readString(scanner : Scanner) : String {static} + } + interface LotteryConsoleService { + + addFundsToLotteryAccount(WireTransfers, Scanner) {abstract} + + checkTicket(LotteryService, Scanner) {abstract} + + queryLotteryAccountFunds(WireTransfers, Scanner) {abstract} + + submitTicket(LotteryService, Scanner) {abstract} + } + class LotteryConsoleServiceImpl { + - logger : Logger + + LotteryConsoleServiceImpl(logger : Logger) + + addFundsToLotteryAccount(bank : WireTransfers, scanner : Scanner) + + checkTicket(service : LotteryService, scanner : Scanner) + + queryLotteryAccountFunds(bank : WireTransfers, scanner : Scanner) + - readString(scanner : Scanner) : String + + submitTicket(service : LotteryService, scanner : Scanner) + } +} +package com.iluwatar.hexagonal.mongo { + class MongoConnectionPropertiesLoader { + - DEFAULT_HOST : String {static} + - DEFAULT_PORT : int {static} + - LOGGER : Logger {static} + + MongoConnectionPropertiesLoader() + + load() {static} + } +} +package com.iluwatar.hexagonal.domain { + class LotteryAdministration { + - notifications : LotteryEventLog + - repository : LotteryTicketRepository + - wireTransfers : WireTransfers + + LotteryAdministration(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers) + + getAllSubmittedTickets() : Map + + performLottery() : LotteryNumbers + + resetLottery() + } + class LotteryConstants { + + PLAYER_MAX_BALANCE : int {static} + + PRIZE_AMOUNT : int {static} + + SERVICE_BANK_ACCOUNT : String {static} + + SERVICE_BANK_ACCOUNT_BALANCE : int {static} + + TICKET_PRIZE : int {static} + - LotteryConstants() + } + class LotteryNumbers { + + MAX_NUMBER : int {static} + + MIN_NUMBER : int {static} + + NUM_NUMBERS : int {static} + - numbers : Set + - LotteryNumbers() + - LotteryNumbers(givenNumbers : Set) + # canEqual(other : Object) : boolean + + create(givenNumbers : Set) : LotteryNumbers {static} + + createRandom() : LotteryNumbers {static} + + equals(o : Object) : boolean + - generateRandomNumbers() + + getNumbers() : Set + + getNumbersAsString() : String + + hashCode() : int + + toString() : String + } + -class RandomNumberGenerator { + - randomIterator : OfInt + + RandomNumberGenerator(min : int, max : int) + + nextInt() : int + } + class LotteryService { + - notifications : LotteryEventLog + - repository : LotteryTicketRepository + - wireTransfers : WireTransfers + + LotteryService(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers) + + checkTicketForPrize(id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult + + submitTicket(ticket : LotteryTicket) : Optional + } + class LotteryTicketCheckResult { + - prizeAmount : int + - result : CheckResult + + LotteryTicketCheckResult(result : CheckResult) + + LotteryTicketCheckResult(result : CheckResult, prizeAmount : int) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getPrizeAmount() : int + + getResult() : CheckResult + + hashCode() : int + } + enum CheckResult { + + NO_PRIZE {static} + + TICKET_NOT_SUBMITTED {static} + + WIN_PRIZE {static} + + valueOf(name : String) : CheckResult {static} + + values() : CheckResult[] {static} + } + class LotteryTicketId { + - id : int + - numAllocated : AtomicInteger {static} + + LotteryTicketId() + + LotteryTicketId(id : int) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getId() : int + + hashCode() : int + + toString() : String + } + class LotteryUtils { + - LotteryUtils() + + checkTicketForPrize(repository : LotteryTicketRepository, id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult {static} + } +} +package com.iluwatar.hexagonal.banking { + class InMemoryBank { + - accounts : Map {static} + + InMemoryBank() + + getFunds(bankAccount : String) : int + + setFunds(bankAccount : String, amount : int) + + transferFunds(amount : int, sourceAccount : String, destinationAccount : String) : boolean + } + class MongoBank { + - DEFAULT_ACCOUNTS_COLLECTION : String {static} + - DEFAULT_DB : String {static} + - accountsCollection : MongoCollection + - database : MongoDatabase + - mongoClient : MongoClient + + MongoBank() + + MongoBank(dbName : String, accountsCollectionName : String) + + connect() + + connect(dbName : String, accountsCollectionName : String) + + getAccountsCollection() : MongoCollection + + getDatabase() : MongoDatabase + + getFunds(bankAccount : String) : int + + getMongoClient() : MongoClient + + setFunds(bankAccount : String, amount : int) + + transferFunds(amount : int, sourceAccount : String, destinationAccount : String) : boolean + } + interface WireTransfers { + + getFunds(String) : int {abstract} + + setFunds(String, int) {abstract} + + transferFunds(int, String, String) : boolean {abstract} + } +} +package com.iluwatar.hexagonal.database { + class InMemoryTicketRepository { + - tickets : Map {static} + + InMemoryTicketRepository() + + deleteAll() + + findAll() : Map + + findById(id : LotteryTicketId) : Optional + + save(ticket : LotteryTicket) : Optional + } + interface LotteryTicketRepository { + + deleteAll() {abstract} + + findAll() : Map {abstract} + + findById(LotteryTicketId) : Optional {abstract} + + save(LotteryTicket) : Optional {abstract} + } + class MongoTicketRepository { + - DEFAULT_COUNTERS_COLLECTION : String {static} + - DEFAULT_DB : String {static} + - DEFAULT_TICKETS_COLLECTION : String {static} + - TICKET_ID : String {static} + - countersCollection : MongoCollection + - database : MongoDatabase + - mongoClient : MongoClient + - ticketsCollection : MongoCollection + + MongoTicketRepository() + + MongoTicketRepository(dbName : String, ticketsCollectionName : String, countersCollectionName : String) + + connect() + + connect(dbName : String, ticketsCollectionName : String, countersCollectionName : String) + + deleteAll() + - docToTicket(doc : Document) : LotteryTicket + + findAll() : Map + + findById(id : LotteryTicketId) : Optional + + getCountersCollection() : MongoCollection + + getNextId() : int + + getTicketsCollection() : MongoCollection + - initCounters() + + save(ticket : LotteryTicket) : Optional + } +} +package com.iluwatar.hexagonal { + class App { + + App() + + main(args : String[]) {static} + } +} +package com.iluwatar.hexagonal.administration { + class ConsoleAdministration { + - LOGGER : Logger {static} + + ConsoleAdministration() + + main(args : String[]) {static} + - printMainMenu() {static} + - readString(scanner : Scanner) : String {static} + } + interface ConsoleAdministrationSrv { + + getAllSubmittedTickets() {abstract} + + performLottery() {abstract} + + resetLottery() {abstract} + } + class ConsoleAdministrationSrvImpl { + - administration : LotteryAdministration + - logger : Logger + + ConsoleAdministrationSrvImpl(administration : LotteryAdministration, logger : Logger) + + getAllSubmittedTickets() + + performLottery() + + resetLottery() + } +} +package com.iluwatar.hexagonal.eventlog { + interface LotteryEventLog { + + prizeError(PlayerDetails, int) {abstract} + + ticketDidNotWin(PlayerDetails) {abstract} + + ticketSubmitError(PlayerDetails) {abstract} + + ticketSubmitted(PlayerDetails) {abstract} + + ticketWon(PlayerDetails, int) {abstract} + } + class MongoEventLog { + - DEFAULT_DB : String {static} + - DEFAULT_EVENTS_COLLECTION : String {static} + - EMAIL : String {static} + + MESSAGE : String {static} + - PHONE : String {static} + - database : MongoDatabase + - eventsCollection : MongoCollection + - mongoClient : MongoClient + - stdOutEventLog : StdOutEventLog + + MongoEventLog() + + MongoEventLog(dbName : String, eventsCollectionName : String) + + connect() + + connect(dbName : String, eventsCollectionName : String) + + getDatabase() : MongoDatabase + + getEventsCollection() : MongoCollection + + getMongoClient() : MongoClient + + prizeError(details : PlayerDetails, prizeAmount : int) + + ticketDidNotWin(details : PlayerDetails) + + ticketSubmitError(details : PlayerDetails) + + ticketSubmitted(details : PlayerDetails) + + ticketWon(details : PlayerDetails, prizeAmount : int) + } + class StdOutEventLog { + - LOGGER : Logger {static} + + StdOutEventLog() + + prizeError(details : PlayerDetails, prizeAmount : int) + + ticketDidNotWin(details : PlayerDetails) + + ticketSubmitError(details : PlayerDetails) + + ticketSubmitted(details : PlayerDetails) + + ticketWon(details : PlayerDetails, prizeAmount : int) + } +} +LotteryAdministration --> "-wireTransfers" WireTransfers +LotteryService --> "-notifications" LotteryEventLog +LotteryAdministration --> "-repository" LotteryTicketRepository +MongoEventLog --> "-stdOutEventLog" StdOutEventLog +LotteryService --> "-wireTransfers" WireTransfers +LotteryAdministration --> "-notifications" LotteryEventLog +ConsoleAdministrationSrvImpl --> "-administration" LotteryAdministration +LotteryService --> "-repository" LotteryTicketRepository +LotteryTicketCheckResult --> "-result" CheckResult +ConsoleAdministrationSrvImpl ..|> ConsoleAdministrationSrv +InMemoryBank ..|> WireTransfers +MongoBank ..|> WireTransfers +InMemoryTicketRepository ..|> LotteryTicketRepository +MongoTicketRepository ..|> LotteryTicketRepository +MongoEventLog ..|> LotteryEventLog +StdOutEventLog ..|> LotteryEventLog +LotteryConsoleServiceImpl ..|> LotteryConsoleService +@enduml \ No newline at end of file diff --git a/marker-interface/etc/marker-interface.urm.puml b/marker-interface/etc/marker-interface.urm.puml new file mode 100644 index 000000000000..02af47ddf261 --- /dev/null +++ b/marker-interface/etc/marker-interface.urm.puml @@ -0,0 +1,2 @@ +@startuml +@enduml \ No newline at end of file diff --git a/microservices-aggregrator/etc/microservices-aggregrator.urm.puml b/microservices-aggregrator/etc/microservices-aggregrator.urm.puml new file mode 100644 index 000000000000..02af47ddf261 --- /dev/null +++ b/microservices-aggregrator/etc/microservices-aggregrator.urm.puml @@ -0,0 +1,2 @@ +@startuml +@enduml \ No newline at end of file diff --git a/microservices-api-gateway/etc/microservices-api-gateway.urm.puml b/microservices-api-gateway/etc/microservices-api-gateway.urm.puml new file mode 100644 index 000000000000..02af47ddf261 --- /dev/null +++ b/microservices-api-gateway/etc/microservices-api-gateway.urm.puml @@ -0,0 +1,2 @@ +@startuml +@enduml \ No newline at end of file diff --git a/microservices-idempotent-consumer/etc/microservices-idempotent-consumer.urm.puml b/microservices-idempotent-consumer/etc/microservices-idempotent-consumer.urm.puml new file mode 100644 index 000000000000..43fe77181375 --- /dev/null +++ b/microservices-idempotent-consumer/etc/microservices-idempotent-consumer.urm.puml @@ -0,0 +1,49 @@ +@startuml +package com.iluwatar.idempotentconsumer { + class App { + - LOGGER : Logger {static} + + App() + + main(args : String[]) {static} + + run(requestService : RequestService, requestRepository : RequestRepository) : CommandLineRunner + } + class Request { + - status : Status + - uuid : UUID + + Request() + + Request(uuid : UUID) + + Request(uuid : UUID, status : Status) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getStatus() : Status + + getUuid() : UUID + + hashCode() : int + + setStatus(status : Status) + + setUuid(uuid : UUID) + + toString() : String + } + ~enum Status { + + COMPLETED {static} + + PENDING {static} + + STARTED {static} + + valueOf(name : String) : Status {static} + + values() : Status[] {static} + } + interface RequestRepository { + } + class RequestService { + ~ requestRepository : RequestRepository + ~ requestStateMachine : RequestStateMachine + + RequestService(requestRepository : RequestRepository, requestStateMachine : RequestStateMachine) + + complete(uuid : UUID) : Request + + create(uuid : UUID) : Request + + start(uuid : UUID) : Request + } + class RequestStateMachine { + + RequestStateMachine() + + next(req : Request, nextStatus : Status) : Request + } +} +RequestService --> "-requestRepository" RequestRepository +Request --> "-status" Status +RequestService --> "-requestStateMachine" RequestStateMachine +@enduml \ No newline at end of file diff --git a/microservices-log-aggregation/etc/microservices-log-aggregation.urm.puml b/microservices-log-aggregation/etc/microservices-log-aggregation.urm.puml new file mode 100644 index 000000000000..1d4551ed025f --- /dev/null +++ b/microservices-log-aggregation/etc/microservices-log-aggregation.urm.puml @@ -0,0 +1,68 @@ +@startuml +package com.iluwatar.logaggregation { + class App { + + App() + + main(args : String[]) {static} + } + class CentralLogStore { + - LOGGER : Logger {static} + - logs : ConcurrentLinkedQueue + + CentralLogStore() + + displayLogs() + + storeLog(logEntry : LogEntry) + } + class LogAggregator { + - BUFFER_THRESHOLD : int {static} + - LOGGER : Logger {static} + - buffer : ConcurrentLinkedQueue + - centralLogStore : CentralLogStore + - executorService : ExecutorService + - logCount : AtomicInteger + - minLogLevel : LogLevel + + LogAggregator(centralLogStore : CentralLogStore, minLogLevel : LogLevel) + + collectLog(logEntry : LogEntry) + - flushBuffer() + - startBufferFlusher() + + stop() + } + class LogEntry { + - level : LogLevel + - message : String + - serviceName : String + - timestamp : LocalDateTime + + LogEntry(serviceName : String, level : LogLevel, message : String, timestamp : LocalDateTime) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getLevel() : LogLevel + + getMessage() : String + + getServiceName() : String + + getTimestamp() : LocalDateTime + + hashCode() : int + + setLevel(level : LogLevel) + + setMessage(message : String) + + setServiceName(serviceName : String) + + setTimestamp(timestamp : LocalDateTime) + + toString() : String + } + enum LogLevel { + + DEBUG {static} + + ERROR {static} + + INFO {static} + + valueOf(name : String) : LogLevel {static} + + values() : LogLevel[] {static} + } + class LogProducer { + - LOGGER : Logger {static} + - aggregator : LogAggregator + - serviceName : String + + LogProducer(serviceName : String, aggregator : LogAggregator) + + generateLog(level : LogLevel, message : String) + } +} +LogAggregator --> "-centralLogStore" CentralLogStore +LogEntry --> "-level" LogLevel +CentralLogStore --> "-logs" LogEntry +LogAggregator --> "-buffer" LogEntry +LogAggregator --> "-minLogLevel" LogLevel +LogProducer --> "-aggregator" LogAggregator +@enduml \ No newline at end of file diff --git a/pom.xml b/pom.xml index ef3a39265d53..6692720741cc 100644 --- a/pom.xml +++ b/pom.xml @@ -218,6 +218,7 @@ function-composition microservices-distributed-tracing microservices-idempotent-consumer + FiniteStateMachine diff --git a/queue-based-load-leveling/etc/queue-based-load-leveling.urm.puml b/queue-based-load-leveling/etc/queue-based-load-leveling.urm.puml new file mode 100644 index 000000000000..ca90842d92dd --- /dev/null +++ b/queue-based-load-leveling/etc/queue-based-load-leveling.urm.puml @@ -0,0 +1,44 @@ +@startuml +package com.iluwatar.queue.load.leveling { + class App { + - LOGGER : Logger {static} + - SHUTDOWN_TIME : int {static} + + App() + + main(args : String[]) {static} + } + class Message { + - msg : String + + Message(msg : String) + + getMsg() : String + + toString() : String + } + class MessageQueue { + - LOGGER : Logger {static} + - blkQueue : BlockingQueue + + MessageQueue() + + retrieveMsg() : Message + + submitMsg(msg : Message) + } + class ServiceExecutor { + - LOGGER : Logger {static} + - msgQueue : MessageQueue + + ServiceExecutor(msgQueue : MessageQueue) + + run() + } + interface Task { + + submit(Message) {abstract} + } + class TaskGenerator { + - LOGGER : Logger {static} + - msgCount : int + - msgQueue : MessageQueue + + TaskGenerator(msgQueue : MessageQueue, msgCount : int) + + run() + + submit(msg : Message) + } +} +MessageQueue --> "-blkQueue" Message +ServiceExecutor --> "-msgQueue" MessageQueue +TaskGenerator --> "-msgQueue" MessageQueue +TaskGenerator ..|> Task +@enduml \ No newline at end of file diff --git a/update-header.sh b/update-header.sh index 48da4dcd6125..568d00d52a03 100755 --- a/update-header.sh +++ b/update-header.sh @@ -1,4 +1,29 @@ #!/bin/bash +# +# This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). +# +# The MIT License +# Copyright © 2014-2022 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. +# + # Find all README.md files in subdirectories one level deep # and replace "### " with "## " at the beginning of lines diff --git a/virtual-proxy/etc/virtual-proxy.urm.puml b/virtual-proxy/etc/virtual-proxy.urm.puml new file mode 100644 index 000000000000..e30149e3809e --- /dev/null +++ b/virtual-proxy/etc/virtual-proxy.urm.puml @@ -0,0 +1,26 @@ +@startuml +package com.iluwatar.virtual.proxy { + class App { + + App() + + main(args : String[]) {static} + } + interface ExpensiveObject { + + process() {abstract} + } + class RealVideoObject { + - LOGGER : Logger {static} + + RealVideoObject() + - heavyInitialConfiguration() + + process() + } + class VideoObjectProxy { + - realVideoObject : RealVideoObject + + VideoObjectProxy() + + getRealVideoObject() : RealVideoObject + + process() + } +} +VideoObjectProxy --> "-realVideoObject" RealVideoObject +RealVideoObject ..|> ExpensiveObject +VideoObjectProxy ..|> ExpensiveObject +@enduml \ No newline at end of file