Compare commits

...

18 Commits

Author SHA1 Message Date
Namu
772c5d8452 Fix: Remove sonar job as java version is not compatible with sonarqube (I hate java) 2025-10-06 11:56:48 +02:00
Namu
d38a67e4f6 Fix: try fix the sonar job with java
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 16s
2025-10-06 11:55:05 +02:00
Namu
501467b7d7 Fix: try fix the sonar job with java
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 1m3s
2025-10-06 11:44:15 +02:00
Namu
addedcab4d Refactor: Remove non-relevant modificators on transformContent
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 19s
2025-10-06 11:40:58 +02:00
Namu
5b1619f34e Refactor: Make NotificationDecoration an Interface
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 18s
2025-10-06 11:37:56 +02:00
Namu
b841c81599 Fix: add missing methods in decorator
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 19s
2025-10-06 11:31:32 +02:00
Namu
ca88a009a0 Feat: We can play the code multiple times with different message
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 19s
2025-10-06 11:06:01 +02:00
Namu
9e3b3cdf58 Refactor: move strategies in a package, other minor modification 2025-10-06 11:02:38 +02:00
Namu
48136c1b7d Doc: add documentation and change the message 2025-10-06 10:55:12 +02:00
Namu
160e5d2740 Refactor: Remove unused imports and add final where it should be 2025-10-06 10:46:01 +02:00
Namu
53cda5688f Feat: Decoration can transform notification content more freely
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 19s
2025-10-06 10:43:33 +02:00
Namu
8a7ce73739 Feat: Decoration can transform notification content more freely 2025-10-06 10:43:01 +02:00
Namu
381e3cc9ac Feat: Decorator and facade implemented
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 19s
2025-10-06 09:50:55 +02:00
Namu
d868ec63c9 Refactor: Make the observable match the new Notification logic 2025-10-06 09:15:36 +02:00
Namu
3065d1bfe3 Refactor: Make the sending strategy match the new Notification logic 2025-10-06 09:12:42 +02:00
Namu
5a97669665 Refactor: Make the Notification not send themself but rather create their content 2025-10-06 09:08:51 +02:00
Namu
2ad93f4b91 Doc: Add a text explaining why I won't implement de decorator pattern 2025-10-02 09:57:39 +02:00
Namu
a26a8c6cf1 Feat: Add facade pattern to send notification 2025-10-02 09:35:00 +02:00
28 changed files with 252 additions and 180 deletions

View File

@@ -1,32 +0,0 @@
name: SonarQube Scan
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
jobs:
sonarqube:
name: SonarQube Trigger
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download SonarQube Scanner
run: |
curl -sSLo sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip
unzip sonar-scanner.zip
- name: Run SonarQube Scan
run: |
./sonar-scanner-*/bin/sonar-scanner \
-Dsonar.projectKey=tp1-iaavancee \
-Dsonar.sources=. \
-Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} \
-Dsonar.login=${{ secrets.SONARQUBE_TOKEN }}

View File

@@ -1,31 +1,11 @@
import entities.User;
import utils.*;
import java.util.Arrays;
import static utils.NotificationType.*;
public class Application {
private final NotificationManager notificationManager;
public Application(NotificationManager notificationManager) {
this.notificationManager = notificationManager;
}
public void run() {
NotificationType[] typesThomas = {Sms, Mail, Push};
NotificationType[] typesAlexandre = {Sms, Mail};
SendNotificationStrategy secured = new SecureSendNotificationStrategy(123);
DifferedSendNotificationStrategy differed = new DifferedSendNotificationStrategy(300);
var thomas = new User(0, "Thomas", Arrays.asList(typesThomas), secured);
var alexandre = new User(1, "Alexandre", Arrays.asList(typesAlexandre), differed);
notificationManager.getObservable().addSubscribers(thomas);
notificationManager.getObservable().addSubscribers(alexandre);
notificationManager.getObservable().sendNotifications("C# > Java (mais Rust c'est le goat)");
String[] messages = new String[]{"Bonjour", "You got mail", "Je préfère C#", "Fin !"};
for (final String message: messages) {
SendNotificationFacade.sendNotifications(message);
}
}
}

View File

@@ -1,8 +1,4 @@
import utils.NotificationManager;
void main(String[] args) {
final var notificationManager = NotificationManager.getInstance();
final var app = new Application(notificationManager);
final var app = new Application();
app.run();
}

View File

@@ -0,0 +1,26 @@
package decorator;
import entities.Notification;
import notificationsDecorations.NotificationDecoration;
public abstract class BaseDecorator {
protected Notification notification;
public BaseDecorator(Notification notification) {
this.notification = notification;
}
public void transitionState() {
notification.transitionState();
}
public void setKoState() {
notification.setKoState();
}
public void addDecoration(NotificationDecoration decoration) {
notification.addDecoration(decoration);
}
public abstract String getContent();
}

View File

@@ -0,0 +1,23 @@
package decorator;
import entities.Notification;
import notificationsDecorations.DateNotificationDecoration;
import java.util.Date;
public class DateDecorator extends BaseDecorator {
public DateDecorator(Notification notification, Date date) {
super(notification);
notification.addDecoration(new DateNotificationDecoration(date));
}
public DateDecorator(BaseDecorator decorator, Date date) {
super(decorator.notification);
notification.addDecoration(new DateNotificationDecoration(date));
}
@Override
public String getContent() {
return notification.getContent();
}
}

View File

@@ -0,0 +1,21 @@
package decorator;
import entities.Notification;
import notificationsDecorations.WatermarkNotificationDecoration;
public class WatermarkDecorator extends BaseDecorator {
public WatermarkDecorator(Notification notification, String watermark) {
super(notification);
notification.addDecoration(new WatermarkNotificationDecoration(watermark));
}
public WatermarkDecorator(BaseDecorator decorator, String watermark) {
super(decorator.notification);
notification.addDecoration(new WatermarkNotificationDecoration(watermark));
}
@Override
public String getContent() {
return this.notification.getContent();
}
}

View File

@@ -1,16 +1,9 @@
package entities;
import utils.SendNotificationStrategy;
import notificationSendingStrategies.SendNotificationStrategy;
public class MailNotification extends Notification {
public MailNotification(String content, User user, SendNotificationStrategy strategy) {
super(content, user, strategy);
}
@Override
public void send() {
if (isSendable())
strategy.send(user.id() + " Mail: " + user.name() + " " + content);
}
}

View File

@@ -1,11 +1,20 @@
package entities;
import notificationsDecorations.NotificationDecoration;
import utils.NotificationState;
import utils.SendNotificationStrategy;
import notificationSendingStrategies.SendNotificationStrategy;
import java.util.ArrayList;
import java.util.List;
public abstract class Notification {
protected String content;
protected User user;
protected List<NotificationDecoration> decorations;
/**
* Pas de change state car chemin multiple. On reste sur des enum !
*/
protected NotificationState state;
protected SendNotificationStrategy strategy;
@@ -14,11 +23,55 @@ public abstract class Notification {
this.user = user;
this.state = NotificationState.PENDING;
this.strategy = strategy;
this.decorations = new ArrayList<>();
}
/**
* Adds a decoration to the notification. Please use a decorator for that
* @param decoration The decoration you want to add
*/
public void addDecoration(NotificationDecoration decoration) {
decorations.add(decoration);
}
protected boolean isSendable() {
return this.state != NotificationState.SENT && this.state != NotificationState.READ;
}
public abstract void send();
/**
* Set KO state on notification
*/
public void setKoState() {
state = NotificationState.KO;
}
/**
* Make state transition
* PENDING -> SENT
* SENT -> READ
*
*/
public void transitionState() {
switch (state) {
case PENDING -> state = NotificationState.SENT;
case SENT -> state = NotificationState.READ;
}
}
/**
* Generates the content of the notification dynamically with the decoration (if some)
* @return content of the notification
*/
public String getContent() {
if (isSendable() && !content.isEmpty()) {
transitionState();
for (final NotificationDecoration decoration : decorations)
content = decoration.transformContent(content);
return strategy.makeContent(content) + "\n";
}
setKoState();
return "";
}
}

View File

@@ -1,15 +1,9 @@
package entities;
import utils.SendNotificationStrategy;
import notificationSendingStrategies.SendNotificationStrategy;
public class PushNotification extends Notification {
public PushNotification(String content, User user, SendNotificationStrategy strategy) {
super(content, user, strategy);
}
@Override
public void send() {
if (isSendable())
strategy.send(user.id() + " Push: " + user.name() + " " + content);
}
}

View File

@@ -1,16 +1,10 @@
package entities;
import utils.SendNotificationStrategy;
import notificationSendingStrategies.SendNotificationStrategy;
public class SmsNotification extends Notification {
public SmsNotification(String content, User user, SendNotificationStrategy strategy) {
super(content, user, strategy);
}
@Override
public void send() {
if (isSendable())
strategy.send(user.id() + " Sms: " + user.name() + " " + content);
}
}

View File

@@ -1,9 +1,14 @@
package entities;
import utils.NotificationType;
import utils.SendNotificationStrategy;
import notificationSendingStrategies.SendNotificationStrategy;
import java.util.List;
public record User(int id, String name, List<NotificationType> notificationsTypes, SendNotificationStrategy chosenNotificationStrategy) {
public record User(
int id,
String name,
List<NotificationType> notificationsTypes,
SendNotificationStrategy chosenNotificationStrategy
) {
}

View File

@@ -1,4 +1,4 @@
package utils;
package notificationSendingStrategies;
public class DifferedSendNotificationStrategy implements SendNotificationStrategy {
private int delay;
@@ -8,14 +8,14 @@ public class DifferedSendNotificationStrategy implements SendNotificationStrateg
}
@Override
public NotificationState send(String message) {
public String makeContent(String message) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
System.err.println("Cannot wait for differed strategy");
return NotificationState.KO;
message = "";
}
System.out.println(message);
return NotificationState.SENT;
return message;
}
}

View File

@@ -0,0 +1,8 @@
package notificationSendingStrategies;
public class FastSendNotificationStrategy implements SendNotificationStrategy {
@Override
public String makeContent(String message) {
return message;
}
}

View File

@@ -0,0 +1,14 @@
package notificationSendingStrategies;
public class SecureSendNotificationStrategy implements SendNotificationStrategy {
private int key;
public SecureSendNotificationStrategy(int key) {
this.key = key;
}
@Override
public String makeContent(String message) {
return key+"Flcjsdjknesdlkgjsilkqzfjazio"+message+"kjhsdiuhisehifsdhfiuhsuidhuifhjsid";
}
}

View File

@@ -0,0 +1,5 @@
package notificationSendingStrategies;
public interface SendNotificationStrategy {
String makeContent(String message);
}

View File

@@ -0,0 +1,17 @@
package notificationsDecorations;
import java.util.Date;
public class DateNotificationDecoration implements NotificationDecoration {
private final Date date;
public DateNotificationDecoration(Date date) {
super();
this.date = date;
}
@Override
public String transformContent(String content) {
return date.toString() + ": " + content;
}
}

View File

@@ -0,0 +1,9 @@
package notificationsDecorations;
public interface NotificationDecoration {
/**
* Each decoration apply a transformation on the content of the Notifications
* @return the content transformed
*/
String transformContent(String content);
}

View File

@@ -0,0 +1,14 @@
package notificationsDecorations;
public class WatermarkNotificationDecoration implements NotificationDecoration {
private final String waterMark;
public WatermarkNotificationDecoration(String waterMark) {
this.waterMark = waterMark;
}
@Override
public String transformContent(String content) {
return content + "\n" + waterMark;
}
}

View File

@@ -1,9 +0,0 @@
package utils;
public class FastSendNotificationStrategy implements SendNotificationStrategy {
@Override
public NotificationState send(String message) {
System.out.println(message);
return NotificationState.SENT;
}
}

View File

@@ -1,5 +0,0 @@
package utils;
public class NotificationFacade {
}

View File

@@ -1,6 +1,7 @@
package utils;
import entities.*;
import notificationSendingStrategies.SendNotificationStrategy;
public class NotificationFactory {
public Notification createNotification(NotificationType type, String content, User user, SendNotificationStrategy strategy) {

View File

@@ -1,8 +1,12 @@
package utils;
import decorator.BaseDecorator;
import decorator.DateDecorator;
import decorator.WatermarkDecorator;
import entities.User;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class NotificationObservable {
@@ -22,7 +26,9 @@ public class NotificationObservable {
for (final var subscriber : this.subscribers) {
for (final var notificationType : subscriber.notificationsTypes()) {
var notification = factory.createNotification(notificationType, content, subscriber, subscriber.chosenNotificationStrategy());
notification.send();
BaseDecorator decorator = new WatermarkDecorator(new DateDecorator(notification, new Date()), "Thomas");
System.out.println(decorator.getContent());
}
}
}

View File

@@ -1,17 +0,0 @@
package utils;
public class PriorityDecorator {
private boolean isPriority;
public PriorityDecorator(boolean isPriority) {
this.isPriority = isPriority;
}
public boolean isPriority() {
return isPriority;
}
public void setPriority(boolean priority) {
isPriority = priority;
}
}

View File

@@ -1,17 +0,0 @@
package utils;
public class ReceiptDecorator {
boolean received;
public ReceiptDecorator() {
this.received = false;
}
public boolean isReceived() {
return received;
}
public void setReceived(boolean received) {
this.received = received;
}
}

View File

@@ -1,15 +0,0 @@
package utils;
public class SecureSendNotificationStrategy implements SendNotificationStrategy {
private int key;
public SecureSendNotificationStrategy(int key) {
this.key = key;
}
@Override
public NotificationState send(String message) {
System.out.println(key+"Flcjsdjknesdlkgjsilkqzfjazio"+message+"kjhsdiuhisehifsdhfiuhsuidhuifhjsid");
return NotificationState.SENT;
}
}

View File

@@ -0,0 +1,32 @@
package utils;
import entities.User;
import notificationSendingStrategies.DifferedSendNotificationStrategy;
import notificationSendingStrategies.SecureSendNotificationStrategy;
import notificationSendingStrategies.SendNotificationStrategy;
import java.util.Arrays;
import static utils.NotificationType.*;
import static utils.NotificationType.Mail;
import static utils.NotificationType.Sms;
public class SendNotificationFacade {
public static void sendNotifications(String message) {
var notificationManager = NotificationManager.getInstance();
NotificationType[] typesThomas = {Sms, Mail, Push};
NotificationType[] typesAlexandre = {Sms, Mail};
SendNotificationStrategy secured = new SecureSendNotificationStrategy(123);
DifferedSendNotificationStrategy differed = new DifferedSendNotificationStrategy(300);
var thomas = new User(0, "Thomas", Arrays.asList(typesThomas), secured);
var alexandre = new User(1, "Alexandre", Arrays.asList(typesAlexandre), differed);
notificationManager.getObservable().addSubscribers(thomas);
notificationManager.getObservable().addSubscribers(alexandre);
notificationManager.getObservable().sendNotifications(message);
}
}

View File

@@ -1,5 +0,0 @@
package utils;
public interface SendNotificationStrategy {
NotificationState send(String message);
}

View File

@@ -1,19 +0,0 @@
package utils;
import java.util.Date;
public class TimeStampDecorator {
private Date time;
public TimeStampDecorator(Date time) {
this.time = time;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}