Merge branch 'feature/#1_développement_code_métier_partie_client' into develop

This commit is contained in:
Notmoo-PC\Notmoo 2017-10-29 09:49:57 +01:00
commit d697c1b123
105 changed files with 1679 additions and 656 deletions

View File

@ -11,7 +11,6 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
<orderEntry type="module" module-name="core" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
</component>

View File

@ -0,0 +1,39 @@
<?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/maven-v4_0_0.xsd">
<parent>
<artifactId>Main</artifactId>
<groupId>com.pqt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>client</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer>
<manifestEntries>
<Main-Class>com.pqt.client.Main</Main-Class>
<Build-Number>1.0-SNAPSHOT</Build-Number>
<Author>Guillaume 'Cess' Prost</Author>
<Last-Update>26/10/2017</Last-Update>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -17,6 +17,35 @@
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<!-- TODO faire un script pour update les data du manifest -->
<Main-Class>com.pqt.client.Main</Main-Class>
<Build-Number>1.0-SNAPSHOT</Build-Number>
<Author>Guillaume 'Cess' Prost</Author>
<Last-Update>26/10/2017</Last-Update>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,21 +1,21 @@
package com.pqt.client;
import com.pqt.client.gui.main_frame.MainFrame;
import com.pqt.client.gui.main_frame.listeners.IMainFrameModelListener;
import com.pqt.client.gui.modules.account_screen.AccountScreen;
import com.pqt.client.gui.modules.sale_screen.SaleScreen;
import com.pqt.client.gui.modules.stat_screen.StatScreen;
import com.pqt.client.gui.modules.stock_screen.StockScreen;
import com.pqt.client.gui.ressources.components.generics.others.SideBar;
import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener;
import com.pqt.client.gui.ressources.components.generics.toast.ToastFactory;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.sale.SaleService;
import com.pqt.client.module.stat.StatService;
import com.pqt.client.module.stock.StockService;
import com.pqt.client.gui.startup_frame.StartupFrame;
import com.pqt.client.gui.startup_frame.listeners.frame.IStartupFrameModelListener;
import com.pqt.client.module.ClientBackEndModuleManager;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Main extends Application{
@ -26,25 +26,53 @@ public class Main extends Application{
@Override
public void start(Stage primaryStage) throws Exception {
SaleService saleService = new SaleService();
StockService stockService = new StockService();
AccountService accountService = new AccountService();
StatService statService = new StatService();
MainFrame mainFrame = new MainFrame(accountService);
mainFrame.addModule(new SaleScreen(accountService, stockService, saleService), true);
mainFrame.addModule(new StockScreen(stockService, accountService));
mainFrame.addModule(new StatScreen(statService));
mainFrame.addModule(new AccountScreen(accountService));
ClientBackEndModuleManager moduleManager = new ClientBackEndModuleManager(null);
Scene scene = new Scene(mainFrame.getPane(), 800, 600);
scene.getStylesheets().clear();
scene.getStylesheets().addAll(getClass().getResource(GUICssTool.getCssFilePath()).toExternalForm());
MainFrame mainFrame = new MainFrame(moduleManager.getAccountService());
mainFrame.addModule(new SaleScreen(moduleManager.getAccountService(), moduleManager.getStockService(), moduleManager.getSaleService()), true);
mainFrame.addModule(new StockScreen(moduleManager.getStockService(), moduleManager.getAccountService()));
mainFrame.addModule(new StatScreen(moduleManager.getStatService()));
mainFrame.addModule(new AccountScreen(moduleManager.getAccountService()));
Scene mainFrameScene = initScene(mainFrame.getPane());
StartupFrame startupFrame = new StartupFrame(moduleManager.getAccountService(), moduleManager.getNetworkService());
Scene startupFrameScene = initScene(startupFrame.getPane());
mainFrame.addFrameModelListener(getMainFrameListener(primaryStage, startupFrameScene));
startupFrame.addFrameModelListener(getStartupFrameListener(primaryStage, mainFrameScene));
ToastFactory.init(primaryStage);
primaryStage.setTitle(GUIStringTool.getAppTitle());
primaryStage.setScene(scene);
primaryStage.setScene(startupFrameScene);
primaryStage.show();
}
private Scene initScene(Pane pane){
Scene scene = new Scene(pane);
scene.getStylesheets().clear();
scene.getStylesheets().addAll(getClass().getResource(GUICssTool.getCssFilePath()).toExternalForm());
return scene;
}
private IStartupFrameModelListener getStartupFrameListener(Stage primaryStage, Scene sceneToDisplay){
return () -> trySwitchScene(primaryStage, sceneToDisplay, true);
}
private IMainFrameModelListener getMainFrameListener(Stage primaryStage, Scene sceneToDisplay){
return () -> trySwitchScene(primaryStage, sceneToDisplay, false);
}
private void trySwitchScene(Stage primaryStage, Scene sceneToDisplay, boolean maximize){
if(sceneToDisplay!=null) {
primaryStage.hide();
primaryStage.setScene(sceneToDisplay);
primaryStage.setMaximized(maximize);
primaryStage.show();
}else{
Platform.exit();
}
}
}

View File

@ -1,7 +1,9 @@
package com.pqt.client.gui.main_frame;
import com.pqt.client.gui.main_frame.listeners.IMainFrameModelListener;
import com.pqt.client.gui.modules.IGuiModule;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.startup_frame.listeners.frame.IStartupFrameModelListener;
import com.pqt.client.module.account.AccountService;
import javafx.scene.layout.Pane;
@ -9,9 +11,10 @@ public class MainFrame implements IFXComponent {
private MainFrameView view;
private MainFrameController ctrl;
private MainFrameModel model;
public MainFrame(AccountService accountService) {
MainFrameModel model = new MainFrameModel(accountService);
model = new MainFrameModel(accountService);
ctrl = new MainFrameController(model);
model.addListener(ctrl);
@ -28,6 +31,10 @@ public class MainFrame implements IFXComponent {
ctrl.addModule(module, false);
}
public void addFrameModelListener(IMainFrameModelListener l){
model.addListener(l);
}
@Override
public Pane getPane() {
return view.getPane();

View File

@ -2,17 +2,12 @@ package com.pqt.client.gui.main_frame;
import com.pqt.client.gui.main_frame.listeners.IMainFrameModelListener;
import com.pqt.client.gui.modules.IGuiModule;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.event.Event;
class MainFrameController implements IMainFrameModelListener {
private MainFrameModel model;
private MainFrameView view;
private IValidatorComponentListener accountManagerAccountListener;
MainFrameController(MainFrameModel model) {
this.model = model;
@ -23,7 +18,6 @@ class MainFrameController implements IMainFrameModelListener {
}
void updateView(){
view.feedAccountCollectionToManager(model.getAccounts());
view.setCurrentAccount(model.getCurrentAccount());
if(model.getCurrentAccount()!=null)
view.updateModuleButtonLock(model.getCurrentAccount().getPermissionLevel());
@ -38,57 +32,12 @@ class MainFrameController implements IMainFrameModelListener {
this.view.addGuiModule(module.getModuleName(),module.getPane(), module.getLowestRequiredAccountLevel(), activate);
}
IValidatorComponentListener getAccountManagerValidatorListener() {
return new IValidatorComponentListener() {
@Override
public void onValidationEvent() {
if(view.isAccountCreationPossible())
model.connectAccount(view.create());
}
@Override
public void onCancelEvent() {
model.disconnectCurrentAccount();
}
};
}
IAccountComponentListener getAccountManagerAccountListener() {
return new IAccountComponentListener() {
@Override
public void onRefreshContentRequestEvent() {
}
@Override
public void onContentClickEvent(Event event, Account eventTarget) {
}
@Override
public void onAddContentRequestEvent() {
}
@Override
public void onRemoveContentRequestEvent(Account content) {
}
@Override
public void onDetailContentRequestEvent(Account content) {
}
};
public void onAccountDisconnectionRequested() {
model.disconnectCurrentAccount();
}
@Override
public void onAccountStatusChangedEvent(boolean status) {
updateView();
}
public void onAccountDisconnectedEvent() {
@Override
public void onAccountCollectionChangedEvent() {
updateView();
}
}

View File

@ -20,37 +20,30 @@ class MainFrameModel {
this.accountService.addListener(new IAccountListener() {
@Override
public void onAccountStatusChangedEvent(boolean status) {
MainFrameModel.this.fireAccountStatusChangedEvent(status);
if(!status){
MainFrameModel.this.fireAccountDisconnectedEvent();
}
}
@Override
public void onAccountStatusNotChangedEvent(Throwable cause) {
}
@Override
public void onAccountListChangedEvent() {
MainFrameModel.this.fireAccountCollectionChangedEvent();
}
});
}
private void fireAccountCollectionChangedEvent() {
Arrays.stream(listenerList.getListeners(IMainFrameModelListener.class)).forEach(IMainFrameModelListener::onAccountCollectionChangedEvent);
}
private void fireAccountStatusChangedEvent(boolean status) {
Arrays.stream(listenerList.getListeners(IMainFrameModelListener.class)).forEach(l->l.onAccountStatusChangedEvent(status));
}
void connectAccount(Account account) {
accountService.setCurrentAccount(account);
accountService.logInCurrentAccount(account.getPassword());
private void fireAccountDisconnectedEvent() {
Arrays.stream(listenerList.getListeners(IMainFrameModelListener.class)).forEach(IMainFrameModelListener::onAccountDisconnectedEvent);
}
void disconnectCurrentAccount() {
accountService.logOutCurrentAccount();
}
Collection<Account> getAccounts(){
return accountService.getAllAccounts();
}
void addListener(IMainFrameModelListener listener){
listenerList.add(IMainFrameModelListener.class, listener);
}

View File

@ -1,6 +1,5 @@
package com.pqt.client.gui.main_frame;
import com.pqt.client.gui.ressources.components.AccountManager;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.components.generics.others.SideBar;
import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener;
@ -10,11 +9,9 @@ import com.pqt.core.entities.user_account.AccountLevel;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ToolBar;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.BorderPane;
@ -22,16 +19,14 @@ import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import java.util.Collection;
class MainFrameView implements IFXComponent{
private final MainFrameController ctrl;
private BorderPane mainPane;
private AccountManager accountManager;
private VBox buttonHolder;
private ObjectProperty<AccountLevel> currentAccountLevel;
private Label accountNameLabel;
MainFrameView(MainFrameController ctrl) {
this.ctrl = ctrl;
@ -51,11 +46,10 @@ class MainFrameView implements IFXComponent{
buttonHolder.prefWidthProperty().bind(sidebar.widthProperty());
sidebar.getChildren().add(buttonHolder);
accountManager = new AccountManager();
accountManager.addListener(ctrl.getAccountManagerValidatorListener());
accountManager.addListener(ctrl.getAccountManagerAccountListener());
accountManager.getPane().prefWidthProperty().bind(sidebar.widthProperty());
sidebar.getChildren().add(accountManager.getPane());
accountNameLabel = new Label();
Button disconnectionButton = new Button(GUIStringTool.getLogoutButtonLabel());
disconnectionButton.setOnAction((event -> ctrl.onAccountDisconnectionRequested()));
sidebar.getChildren().addAll(accountNameLabel, disconnectionButton);
mainPane.setLeft(sidebar);
@ -120,20 +114,8 @@ class MainFrameView implements IFXComponent{
buttonHolder.getChildren().add(button);
}
boolean isAccountCreationPossible(){
return accountManager.isCreationPossible();
}
Account create(){
return accountManager.create();
}
void setCurrentAccount(Account account){
accountManager.setCurrentAccount(account);
}
void feedAccountCollectionToManager(Collection<Account> accounts){
accountManager.display(accounts);
accountNameLabel.setText(GUIStringTool.getAccountStringConverter().toString(account));
}
void updateModuleButtonLock(AccountLevel level) {

View File

@ -3,6 +3,5 @@ package com.pqt.client.gui.main_frame.listeners;
import java.util.EventListener;
public interface IMainFrameModelListener extends EventListener{
void onAccountStatusChangedEvent(boolean status);
void onAccountCollectionChangedEvent();
void onAccountDisconnectedEvent();
}

View File

@ -37,8 +37,6 @@ class AccountScreenModel {
}
Collection<AccountLevel> getLevels() {
//TODO régler ça aussi
//return accountService.getAvailableLevels();
return EnumSet.allOf(AccountLevel.class);
}
}

View File

@ -9,7 +9,6 @@ import javafx.scene.layout.Pane;
import java.util.Collection;
//TODO à faire
public class AccountManagerScreen implements IFXValidatorComponent, IFXCreatorComponent<Account>{
private AccountManagerScreenModel model;

View File

@ -13,7 +13,9 @@ import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.event.Event;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
class SaleScreenController {
@ -45,7 +47,7 @@ class SaleScreenController {
@Override
public void onAccountListUpdatedEvent() {
view.setAccounts(model.getAccountList());
view.setAccounts(new ArrayList<>(model.getAccountList()));
}
@ -99,7 +101,7 @@ class SaleScreenController {
return model.getProductList();
}
private List<Account> fetchAccountList(){
return model.getAccountList();
return new ArrayList<>(model.getAccountList());
}
private List<SaleType> fetchSaleTypeList(){
return model.getSaleTypeList();

View File

@ -17,6 +17,7 @@ import com.pqt.core.entities.user_account.AccountLevel;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@ -104,6 +105,11 @@ class SaleScreenModel {
fireAccountConnectedStatusUpdateEvent();
}
@Override
public void onAccountStatusNotChangedEvent(Throwable cause) {
}
@Override
public void onAccountListChangedEvent() {
fireAccountListUpdatedEvent();
@ -138,7 +144,7 @@ class SaleScreenModel {
.forEach(ISaleScreenModelListener::onAccountConnectedStateUpdatedEvent);
}
List<Account> getAccountList() {
Collection<Account> getAccountList() {
return accountService.getAllAccounts();
}

View File

@ -34,6 +34,11 @@ class StockScreenModel {
StockScreenModel.this.fireConnectedStatusChanged();
}
@Override
public void onAccountStatusNotChangedEvent(Throwable cause) {
}
@Override
public void onAccountListChangedEvent() {

View File

@ -1,162 +0,0 @@
package com.pqt.client.gui.ressources.components;
import com.pqt.client.gui.ressources.components.generics.creators.IFXCreatorComponent;
import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent;
import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.SimpleValidatorComponentFirerer;
import com.pqt.client.gui.ressources.components.specifics.account.IFXAccountsDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.account.listeners.SimpleAccountComponentFirerer;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import java.util.Collection;
public class AccountManager implements IFXAccountsDisplayerComponent, IFXValidatorComponent, IFXCreatorComponent<Account> {
private Pane mainPane;
private VBox mainDisconnectedPane, mainConnectedPane;
private TextField connectedUsernameField;
private ChoiceBox<Account> disconnectedUsernameField;
private PasswordField passwordField;
private SimpleAccountComponentFirerer accountEventFirerer;
private SimpleValidatorComponentFirerer validatorEventFirerer;
private Account currentAccount;
public AccountManager() {
accountEventFirerer = new SimpleAccountComponentFirerer();
validatorEventFirerer = new SimpleValidatorComponentFirerer();
currentAccount = null;
init();
}
private void init() {
mainPane = new Pane();
mainConnectedPane = new VBox();
mainDisconnectedPane = new VBox();
connectedUsernameField = new TextField();
connectedUsernameField.setEditable(false);
Button disconnectButton = new Button(GUIStringTool.getLogoutButtonLabel());
disconnectButton.setOnMouseClicked(event->validatorEventFirerer.fireCancelEvent());
disconnectButton.setOnKeyTyped(event->{if(event.getCode().equals(KeyCode.ENTER)) validatorEventFirerer.fireCancelEvent();});
mainConnectedPane.getChildren().addAll(connectedUsernameField, disconnectButton);
disconnectedUsernameField = new ChoiceBox<>();
disconnectedUsernameField.setConverter(GUIStringTool.getAccountStringConverter());
passwordField = new PasswordField();
passwordField.setPromptText(GUIStringTool.getPasswordFieldPromptText());
Button validationButton = new Button(GUIStringTool.getLoginButtonLabel());
validationButton.setOnMouseClicked(event-> validatorEventFirerer.fireValidationEvent());
validationButton.setOnKeyTyped(event->{if(event.getCode().equals(KeyCode.ENTER)) validatorEventFirerer.fireValidationEvent();});
mainDisconnectedPane.getChildren().addAll(disconnectedUsernameField, passwordField, validationButton);
refreshMainPane();
display(null);
}
@Override
public void display(Collection<Account> content) {
Platform.runLater(()->{
if(content!=null && content.size()>0)
disconnectedUsernameField.setItems(FXCollections.observableArrayList(content));
else{
disconnectedUsernameField.getItems().clear();
disconnectedUsernameField.getItems().add(new Account("null", "", AccountLevel.getLowest()));
}
});
}
public void setCurrentAccount(Account account){
currentAccount = account;
Platform.runLater(()->connectedUsernameField.setText(GUIStringTool.getAccountStringConverter().toString(currentAccount)));
refreshMainPane();
}
private void refreshMainPane() {
if(currentAccount!=null)
Platform.runLater(
()->{
mainPane.getChildren().clear();
mainPane.getChildren().add(mainConnectedPane);
}
);
else
Platform.runLater(
()->{
mainPane.getChildren().clear();
mainPane.getChildren().add(mainDisconnectedPane);
}
);
}
public Account getCurrentAccount() {
return currentAccount;
}
@Override
public void addListener(IAccountComponentListener l) {
accountEventFirerer.addListener(l);
}
@Override
public void removeListener(IAccountComponentListener l) {
accountEventFirerer.removeListener(l);
}
@Override
public Pane getPane() {
return mainPane;
}
@Override
public void addListener(IValidatorComponentListener l) {
validatorEventFirerer.addListener(l);
}
@Override
public void removeListener(IValidatorComponentListener l) {
validatorEventFirerer.removeListener(l);
}
@Override
public Account create() {
if(!isCreationPossible())
return null;
return new Account(disconnectedUsernameField.getValue().getUsername(), passwordField.getText(), disconnectedUsernameField.getValue().getPermissionLevel());
}
@Override
public boolean isCreationPossible() {
return currentAccount==null
&& disconnectedUsernameField.getAccessibleText()!=null
&& !disconnectedUsernameField.getAccessibleText().isEmpty()
&& passwordField.getText()!=null
&& !passwordField.getText().isEmpty();
}
}

View File

@ -1,11 +0,0 @@
package com.pqt.client.gui.ressources.components.specifics.account;
import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener;
import com.pqt.core.entities.user_account.Account;
import java.util.Collection;
public interface IFXAccountsDisplayerComponent extends IFXDisplayerComponent<Collection<Account>, IAccountComponentListener> {
}

View File

@ -1,7 +0,0 @@
package com.pqt.client.gui.ressources.components.specifics.account.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener;
import com.pqt.core.entities.user_account.Account;
public interface IAccountComponentListener extends IDisplayerComponentListener<Account>{
}

View File

@ -1,10 +0,0 @@
package com.pqt.client.gui.ressources.components.specifics.account.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.SimpleDisplayerComponentFirerer;
import com.pqt.core.entities.user_account.Account;
public class SimpleAccountComponentFirerer extends SimpleDisplayerComponentFirerer<Account, IAccountComponentListener> {
public SimpleAccountComponentFirerer() {
super(IAccountComponentListener.class);
}
}

View File

@ -331,6 +331,35 @@ public class GUIStringTool {
public static String getAccountLevelColumnHeaderLabel() {
return "Niveau d'accréditation";
}
public static String getServerSectionTitleLabel() {
return "Serveur";
}
public static String getAccountSectionTitleLabel() {
return "Compte";
}
public static String getErrorConsoleSectionTitleLabel() {
return "Informations";
}
public static String getServerHostLabel() {
return "Host : ";
}
public static String getServerPortLabel() {
return "Port : ";
}
public static IObjectStringRenderer<Exception> getExceptionFormatter() {
return e->{
if(e.getMessage()==null || e.getMessage().isEmpty())
return String.format("%s", e.getClass().getName());
else
return String.format("%s : %s", e.getClass().getName(), e.getMessage());
};
}
}

View File

@ -0,0 +1,32 @@
package com.pqt.client.gui.startup_frame;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.startup_frame.listeners.frame.IStartupFrameModelListener;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.network.NetworkService;
import javafx.scene.layout.Pane;
public class StartupFrame implements IFXComponent{
private StartupFrameView view;
private StartupFrameModel model;
public StartupFrame(AccountService accountService, NetworkService networkService) {
model = new StartupFrameModel(accountService, networkService);
StartupFrameController ctrl = new StartupFrameController(model);
model.addListener(ctrl);
view = new StartupFrameView(ctrl);
ctrl.setView(view);
ctrl.updateView();
}
public void addFrameModelListener(IStartupFrameModelListener l){
model.addListener(l);
}
@Override
public Pane getPane() {
return view.getPane();
}
}

View File

@ -0,0 +1,48 @@
package com.pqt.client.gui.startup_frame;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.gui.startup_frame.listeners.frame.IStartupFrameModelListener;
public class StartupFrameController implements IStartupFrameModelListener {
private final StartupFrameModel model;
private StartupFrameView view;
public StartupFrameController(StartupFrameModel model) {
this.model = model;
}
public void setView(StartupFrameView view) {
this.view = view;
}
public void updateView() {
view.setValidationButtonEnable(enableValidationButton());
}
private boolean enableValidationButton() {
return !view.getAccountUsernameTextFieldContent().isEmpty()
&& !view.getServerPortTextFieldContent().isEmpty()
&& !view.getServerPortTextFieldContent().isEmpty();
}
public void onValidation() {
if(!model.isStartupProcessRunning()){
try {
model.beginStartupProcess(
view.getServerHostTextFieldContent(),
view.getServerPortTextFieldContent(),
view.getAccountUsernameTextFieldContent(),
view.getAccountPasswordTextFieldContent()
);
}catch(NullPointerException | IllegalArgumentException e){
view.displayError(GUIStringTool.getExceptionFormatter().render(e));
}
}
}
@Override
public void onStartupValidated() {
view.clearPasswordField();
}
}

View File

@ -0,0 +1,77 @@
package com.pqt.client.gui.startup_frame;
import com.pqt.client.gui.startup_frame.listeners.frame.IStartupFrameModelEventFirerer;
import com.pqt.client.gui.startup_frame.listeners.frame.IStartupFrameModelListener;
import com.pqt.client.gui.startup_frame.listeners.frame.SimpleStartupFrameModelEventFirerer;
import com.pqt.client.gui.startup_frame.listeners.procedure.IStartupProcedureListener;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.network.NetworkService;
public class StartupFrameModel {
private final AccountService accountService;
private final NetworkService networkService;
private final IStartupFrameModelEventFirerer firerer;
private boolean startupProcessBegan;
public StartupFrameModel(AccountService accountService, NetworkService networkService) {
this.accountService = accountService;
this.networkService = networkService;
firerer = new SimpleStartupFrameModelEventFirerer();
startupProcessBegan = false;
}
public void addListener(IStartupFrameModelListener ctrl) {
firerer.addListener(ctrl);
}
public boolean isStartupProcessRunning() {
return startupProcessBegan;
}
public void beginStartupProcess(String requiredHost, String requiredPort, String username, String password) {
if(!startupProcessBegan){
checkParameters(requiredHost, requiredPort, username, password);
startupProcessBegan = true;
Integer requiredIntPort = Integer.parseInt(requiredPort);
new StartupProcedureHandler(networkService, accountService)
.init(requiredHost, requiredIntPort, username, password)
.addListener(new IStartupProcedureListener() {
@Override
public void onServerFoundEvent(String URL, Integer Port) {
}
@Override
public void onUserAccountUnknownEvent(String username) {
}
@Override
public void onUserAccountConnectedEvent(String username) {
firerer.fireStartupValidated();
}
@Override
public void onUserAccountDisconnectedEvent(String username) {
}
})
.handle();
}
}
private void checkParameters(String host, String port, String username, String password) {
if(host==null || port == null || username == null || password == null)
throw new NullPointerException("Null parameters are not allowed on startup");
if(username.isEmpty() || host.isEmpty() || port.isEmpty())
throw new IllegalArgumentException("The following parameters must be filled : host, port, username");
if(!port.matches("^\\d+$"))
throw new IllegalArgumentException("Given port is not a positive integer");
}
}

View File

@ -0,0 +1,115 @@
package com.pqt.client.gui.startup_frame;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
public class StartupFrameView implements IFXComponent{
private VBox mainPane;
private final StartupFrameController ctrl;
private TextField serverHostTextField;
private TextField serverPortTextField;
private TextField usernameTextField;
private TextField passwordTextField;
private Button validationButton;
private Text infoText;
public StartupFrameView(StartupFrameController ctrl) {
this.ctrl = ctrl;
initGui();
}
private void initGui() {
try {
mainPane = new VBox();
Label serverHostLabel = new Label(GUIStringTool.getServerHostLabel());
serverHostTextField = makeTextField(TextField.class);
Label serverPortLabel = new Label(GUIStringTool.getServerPortLabel());
serverPortTextField = makeTextField(TextField.class);
GridPane serverFieldGridPane = new GridPane();
serverFieldGridPane.add(serverHostLabel, 0, 0);
serverFieldGridPane.add(serverHostTextField, 1, 0);
serverFieldGridPane.add(serverPortLabel, 0, 1);
serverFieldGridPane.add(serverPortTextField, 1, 1);
TitledPane serverTitledPane = new TitledPane(GUIStringTool.getServerSectionTitleLabel(), serverFieldGridPane);
Label usernameLabel = new Label(GUIStringTool.getUsernameLabel());
usernameTextField = makeTextField(TextField.class);
Label passwordLabel = new Label(GUIStringTool.getPasswordLabel());
passwordTextField = makeTextField(PasswordField.class);
GridPane accountFieldGridPane = new GridPane();
accountFieldGridPane.add(usernameLabel, 0, 0);
accountFieldGridPane.add(usernameTextField, 1, 0);
accountFieldGridPane.add(passwordLabel, 0, 1);
accountFieldGridPane.add(passwordTextField, 1, 1);
TitledPane accountTitledPane = new TitledPane(GUIStringTool.getAccountSectionTitleLabel(), accountFieldGridPane);
validationButton = new Button(GUIStringTool.getValidationButtonLabel());
validationButton.setOnAction((event) -> {
ctrl.onValidation();
});
infoText = new Text("");
infoText.getStyleClass().add("text-displayer");
TitledPane errorConsoleTitledPane = new TitledPane(GUIStringTool.getErrorConsoleSectionTitleLabel(), infoText);
infoText.textProperty().addListener((obs, oldValue, newValue)->errorConsoleTitledPane.setExpanded(true));
mainPane.getChildren().addAll(serverTitledPane, accountTitledPane, errorConsoleTitledPane, validationButton);
}catch(Exception e){
//TODO Shutdown software on exception
e.printStackTrace();
}
}
private <T extends TextField> T makeTextField(Class<T> clazz) throws IllegalAccessException, InstantiationException {
T ntf = clazz.newInstance();
ntf.textProperty().addListener((obs, oldVal, newVal)->{
ctrl.updateView();
});
return ntf;
}
String getServerHostTextFieldContent(){
return serverHostTextField.getText();
}
String getServerPortTextFieldContent(){
return serverPortTextField.getText();
}
String getAccountUsernameTextFieldContent(){
return usernameTextField.getText();
}
String getAccountPasswordTextFieldContent(){
return passwordTextField.getText();
}
@Override
public Pane getPane() {
return mainPane;
}
public void setValidationButtonEnable(boolean enable) {
this.validationButton.setDisable(!enable);
}
public void clearPasswordField() {
passwordTextField.setText("");
}
public void displayError(String errorMsg) {
infoText.setText(errorMsg);
}
}

View File

@ -0,0 +1,124 @@
package com.pqt.client.gui.startup_frame;
import com.pqt.client.gui.startup_frame.listeners.procedure.IStartupProcedureEventFirerer;
import com.pqt.client.gui.startup_frame.listeners.procedure.IStartupProcedureListener;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.account.listeners.AccountListenerAdapter;
import com.pqt.client.module.account.listeners.IAccountListener;
import com.pqt.client.module.network.NetworkService;
import com.pqt.client.module.network.listeners.INetworkServiceListener;
import com.pqt.core.entities.user_account.Account;
class StartupProcedureHandler {
private NetworkService networkService;
private AccountService accountService;
private String host, username, password;
private Integer port;
private IStartupProcedureEventFirerer firerer;
StartupProcedureHandler(NetworkService networkService, AccountService accountService) {
this.networkService = networkService;
this.accountService = accountService;
}
StartupProcedureHandler init(String host, Integer port, String username, String password){
this.host = host;
this.port = port;
this.username = username;
this.password = password;
return this;
}
void handle(){
testConnection();
}
private void testConnection(){
networkService.addListener(getPingListener());
networkService.sendPQTPing(host, port);
}
private void useRequestedServer(){
//Server found
firerer.fireServerFoundEvent(host, port);
networkService.setActiveServer(host, port);
accountService.addListener(getUpdateAccountListListener());
accountService.refreshAccounts();
}
private void connectAccount(){
Account match = accountService.getAllAccounts().stream()
.filter(account -> account.getUsername().equals(username))
.findFirst()
.orElse(null);
if(match==null){
//Compte spécifié inconnu
firerer.fireUserAccountUnknownEvent(username);
}else{
accountService.setCurrentAccount(match);
accountService.addListener(getConnectAccountListener());
accountService.logInCurrentAccount(StartupProcedureHandler.this.password);
}
}
private INetworkServiceListener getPingListener(){
return new INetworkServiceListener() {
@Override
public void onPQTPingSuccessEvent(String host, Integer port) {
if(StartupProcedureHandler.this.host.equals(host)
&& StartupProcedureHandler.this.port.equals(port)){
useRequestedServer();
}
}
@Override
public void onPQTPingFailureEvent(String host, Integer port, Throwable cause) {
}
@Override
public void onNewServerConfigData() {
}
};
}
private IAccountListener getUpdateAccountListListener(){
return new AccountListenerAdapter(){
@Override
public void onAccountListChangedEvent(){
connectAccount();
}
};
}
private IAccountListener getConnectAccountListener(){
return new AccountListenerAdapter(){
@Override
public void onAccountStatusChangedEvent(boolean status) {
if(status){
//Compte connecté
firerer.fireUserAccountConnectedEvent(username);
}else{
//Compte non-connecté
firerer.fireUserAccountDisconnectedEvent(username);
}
}
};
}
public StartupProcedureHandler addListener(IStartupProcedureListener l){
firerer.addListener(l);
return this;
}
public StartupProcedureHandler removeListener(IStartupProcedureListener l){
firerer.removeListener(l);
return this;
}
}

View File

@ -0,0 +1,8 @@
package com.pqt.client.gui.startup_frame.listeners.frame;
public interface IStartupFrameModelEventFirerer {
void fireStartupValidated();
void addListener(IStartupFrameModelListener l);
void removeListener(IStartupFrameModelListener l);
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.gui.startup_frame.listeners.frame;
import java.util.EventListener;
public interface IStartupFrameModelListener extends EventListener {
void onStartupValidated();
}

View File

@ -0,0 +1,29 @@
package com.pqt.client.gui.startup_frame.listeners.frame;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
public class SimpleStartupFrameModelEventFirerer implements IStartupFrameModelEventFirerer {
private final EventListenerList listenerList;
public SimpleStartupFrameModelEventFirerer() {
this.listenerList = new EventListenerList();
}
@Override
public void fireStartupValidated() {
Arrays.stream(listenerList.getListeners(IStartupFrameModelListener.class))
.forEach(IStartupFrameModelListener::onStartupValidated);
}
@Override
public void addListener(IStartupFrameModelListener l) {
listenerList.add(IStartupFrameModelListener.class, l);
}
@Override
public void removeListener(IStartupFrameModelListener l) {
listenerList.remove(IStartupFrameModelListener.class, l);
}
}

View File

@ -0,0 +1,12 @@
package com.pqt.client.gui.startup_frame.listeners.procedure;
public interface IStartupProcedureEventFirerer {
void fireServerFoundEvent(String URL, Integer Port);
void fireUserAccountUnknownEvent(String username);
void fireUserAccountConnectedEvent(String username);
void fireUserAccountDisconnectedEvent(String username);
void addListener(IStartupProcedureListener l );
void removeListener(IStartupProcedureListener l );
}

View File

@ -0,0 +1,11 @@
package com.pqt.client.gui.startup_frame.listeners.procedure;
import java.util.EventListener;
public interface IStartupProcedureListener extends EventListener{
void onServerFoundEvent(String URL, Integer Port);
void onUserAccountUnknownEvent(String username);
void onUserAccountConnectedEvent(String username);
void onUserAccountDisconnectedEvent(String username);
}

View File

@ -0,0 +1,47 @@
package com.pqt.client.gui.startup_frame.listeners.procedure;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
public class SimpleStartupProcedureEventFirerer implements IStartupProcedureEventFirerer {
private final EventListenerList listenerList;
public SimpleStartupProcedureEventFirerer() {
this.listenerList = new EventListenerList();
}
@Override
public void fireServerFoundEvent(String URL, Integer port) {
Arrays.stream(listenerList.getListeners(IStartupProcedureListener.class))
.forEach(l->l.onServerFoundEvent(URL, port));
}
@Override
public void fireUserAccountUnknownEvent(String username) {
Arrays.stream(listenerList.getListeners(IStartupProcedureListener.class))
.forEach(l->l.onUserAccountUnknownEvent(username));
}
@Override
public void fireUserAccountConnectedEvent(String username) {
Arrays.stream(listenerList.getListeners(IStartupProcedureListener.class))
.forEach(l->l.onUserAccountConnectedEvent(username));
}
@Override
public void fireUserAccountDisconnectedEvent(String username) {
Arrays.stream(listenerList.getListeners(IStartupProcedureListener.class))
.forEach(l->l.onUserAccountDisconnectedEvent(username));
}
@Override
public void addListener(IStartupProcedureListener l) {
listenerList.add(IStartupProcedureListener.class, l);
}
@Override
public void removeListener(IStartupProcedureListener l) {
listenerList.remove(IStartupProcedureListener.class, l);
}
}

View File

@ -0,0 +1,48 @@
package com.pqt.client.module;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.connection.ConnectionService;
import com.pqt.client.module.network.NetworkService;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.client.module.sale.SaleService;
import com.pqt.client.module.stat.StatService;
import com.pqt.client.module.stock.StockService;
public class ClientBackEndModuleManager {
private final SaleService saleService;
private final StockService stockService;
private final AccountService accountService;
private final StatService statService;
private final NetworkService networkService;
public ClientBackEndModuleManager(String serverUrl) {
ConnectionService connectionService = new ConnectionService(serverUrl);
QueryExecutor queryExecutor = new QueryExecutor(connectionService);
saleService = new SaleService(queryExecutor);
stockService = new StockService(queryExecutor);
accountService = new AccountService(queryExecutor);
statService = new StatService(queryExecutor);
networkService = new NetworkService(queryExecutor, connectionService);
}
public SaleService getSaleService() {
return saleService;
}
public StockService getStockService() {
return stockService;
}
public AccountService getAccountService() {
return accountService;
}
public StatService getStatService() {
return statService;
}
public NetworkService getNetworkService() {
return networkService;
}
}

View File

@ -1,48 +1,123 @@
package com.pqt.client.module.account;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.client.module.query.query_callback.ICollectionItemMessageCallback;
import com.pqt.client.module.query.query_callback.INoItemMessageCallback;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.user_account.Account;
import com.pqt.client.module.account.listeners.IAccountListener;
import javax.swing.event.EventListenerList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
//TODO écrire contenu méthodes
//TODO écrire javadoc
//TODO add log lines
//TODO supporter la modif de comptes
public class AccountService {
private QueryExecutor executor;
private Account currentAccount;
private boolean connected;
private Collection<Account> accounts;
private EventListenerList listenerList;
public AccountService(QueryExecutor executor){
this.executor = executor;
listenerList = new EventListenerList();
accounts = new ArrayList<>();
}
public Account getCurrentAccount() {
return null;
return currentAccount;
}
public void setCurrentAccount(Account account) {
if(connected)
logOutCurrentAccount();
this.currentAccount = account;
}
public boolean isCurrentAccountLoggedIn() {
return false;
return connected;
}
public void logInCurrentAccount(String password) {
setCurrentAccountState(password, true);
}
public void logOutCurrentAccount() {
setCurrentAccountState(null, false);
}
public List<Account> getRecentAccounts() {
return null;
}
private void setCurrentAccountState(String password, boolean state){
if(currentAccount!=null && connected!=state) {
Account acc = new Account(currentAccount);
acc.setPassword(password);
executor.executeConnectAccountQuery(acc, state, new INoItemMessageCallback() {
@Override
public void ack() {
if (currentAccount != null
&& connected != state
&& currentAccount.getUsername().equals(acc.getUsername())
&& currentAccount.getPermissionLevel().equals(acc.getPermissionLevel())) {
connected = state;
Arrays.stream(listenerList.getListeners(IAccountListener.class))
.forEach(l->l.onAccountStatusChangedEvent(connected));
}else
Arrays.stream(listenerList.getListeners(IAccountListener.class))
.forEach(l->l.onAccountStatusNotChangedEvent(
new IllegalStateException("Account service not in the right state")
));
}
@Override
public void err(Throwable cause) {
Arrays.stream(listenerList.getListeners(IAccountListener.class))
.forEach(l->l.onAccountStatusNotChangedEvent(cause));
}
@Override
public void ref(Throwable cause) {
Arrays.stream(listenerList.getListeners(IAccountListener.class))
.forEach(l->l.onAccountStatusNotChangedEvent(cause));
}
});
}
}
public void addListener(IAccountListener listener) {
listenerList.add(IAccountListener.class, listener);
}
public void removeListener(IAccountListener listener) {
listenerList.remove(IAccountListener.class, listener);
}
public List<Account> getAllAccounts() {
return null;
public Collection<Account> getAllAccounts() {
return accounts;
}
public void refreshAccounts(){
executor.executeAccountListQuery(new ICollectionItemMessageCallback<Account>() {
@Override
public void err(Throwable cause) {
}
@Override
public void ref(Throwable cause) {
}
@Override
public void ack(Collection<Account> obj) {
accounts = obj;
Arrays.stream(listenerList.getListeners(IAccountListener.class))
.forEach(IAccountListener::onAccountListChangedEvent);
}
});
}
}

View File

@ -8,13 +8,23 @@ public class AccountListenerAdapter implements IAccountListener {
/**
* @see com.pqt.client.module.account.listeners.IAccountListener#onAccountStatusChangedEvent(boolean)
*/
@Override
public void onAccountStatusChangedEvent(boolean status) {
}
/**
* @see com.pqt.client.module.account.listeners.IAccountListener#onAccountStatusNotChangedEvent(Throwable)
*/
@Override
public void onAccountStatusNotChangedEvent(Throwable cause) {
}
/**
* @see com.pqt.client.module.account.listeners.IAccountListener#onAccountListChangedEvent()
*/
@Override
public void onAccountListChangedEvent() {
}

View File

@ -5,5 +5,6 @@ import java.util.EventListener;
public interface IAccountListener extends EventListener {
void onAccountStatusChangedEvent(boolean status);
void onAccountStatusNotChangedEvent(Throwable cause);
void onAccountListChangedEvent();
}

View File

@ -1,46 +1,66 @@
package com.pqt.client.module.connection;
import com.pqt.client.module.connection.listeners.IConnectionListener;
import com.pqt.client.module.connection.senders.HttpTextSender;
import com.pqt.client.module.connection.senders.ITextSender;
import java.util.concurrent.*;
//TODO écrire contenu méthodes
//TODO écrire javadoc
//TODO add log lines?
public class ConnectionService {
public boolean isConnectedToServer() {
return false;
private String serverUrl;
private ExecutorService executor;
private ITextSender textSender;
public ConnectionService(String serverUrl) {
executor = new ThreadPoolExecutor(1, 1, 1000,
TimeUnit.SECONDS, new LinkedBlockingQueue<>());
this.serverUrl = serverUrl;
this.textSender = new HttpTextSender();
}
public String getServerUrl() {
return serverUrl;
}
public void connectToServer(String ip_address) {
}
public void disconnectFromServer() {
}
public String getCurrentServerIpAddress() {
return null;
}
public void start() {
}
public void stop() {
}
public void sendText(String text) {
}
public void addListener(IConnectionListener listener) {
}
public void removeListener(IConnectionListener listener) {
public void setServerUrl(String url){
this.serverUrl = url;
}
/**
* Arrête le service d'envoi.
* <p/>
* <b>Si ce service est arrêté, il ne sera plus possible de l'utiliser, et ne pourra pas être redémarré</b>. Une
* autre isntance devra être utilisée pour pouvoir recommencer à se servir de ce service.
* <p/>
* Si {@code force} vaut true, le service tentera d'interrompre tous les envois de texte en cours, même s'il ne
* sont pas terminés. Sinon, le service attendra que tous les envois en cours soient terminé avant de s'arrêter, mais
* n'acceptera pas de nouveaux envois.
* @param force {@code true} si l'arrêt du service doit être forcé, {@code false} sinon
*/
public void stop(boolean force) {
if(executor!=null)
if(force)
executor.shutdownNow();
else
executor.shutdown();
}
/**
* Envoie la chaîne de caractères {@code text} au serveur de donnée correspondant à l'URL {@link #getServerUrl()}, et
* utilise {@code listener} pour notifier l'avancement de l'envoi.
*
* @param text texte à envoyer
* @param listener listener à utiliser pour notifier l'avancement de l'envoi (voir {@link IConnectionListener})
* @throws IllegalStateException Si l'url du serveur vaut {@code null} (à spécifier à la constructyion ou avec
* {@link #setServerUrl(String)}, ou si le service à été arrêté via la méthode {@link #stop(boolean)}.
*/
public void sendText(String text, IConnectionListener listener) throws IllegalStateException{
if(serverUrl==null)
throw new IllegalStateException("No url specified for data server");
if(executor.isShutdown() || executor.isTerminated())
throw new IllegalStateException("Service was shut down : unable to send text");
executor.submit(()->textSender.send(serverUrl, text, listener));
}
}

View File

@ -1,7 +1,5 @@
package com.pqt.client.module.connection.listeners;
//TODO écrire contenu méthodes
//TODO écrire javadoc
public class ConnectionListenerAdapter implements IConnectionListener {
@ -10,6 +8,7 @@ public class ConnectionListenerAdapter implements IConnectionListener {
*
*
*/
@Override
public void onMessageReceivedEvent(String msg) {
}
@ -20,6 +19,7 @@ public class ConnectionListenerAdapter implements IConnectionListener {
*
*
*/
@Override
public void onConnectedEvent() {
}
@ -30,8 +30,20 @@ public class ConnectionListenerAdapter implements IConnectionListener {
*
*
*/
@Override
public void onDisconnectedEvent() {
}
/**
* @see com.pqt.client.module.connection.listeners.IConnectionListener#onTimeOutEvent()
*
*
*/
@Override
public void onTimeOutEvent() {
}
}

View File

@ -2,14 +2,16 @@ package com.pqt.client.module.connection.listeners;
public interface IConnectionFirerer {
public abstract void fireMessageReceivedEvent(String msg);
void fireMessageReceivedEvent(String msg);
public abstract void fireConnectedEvent();
void fireConnectedEvent();
public abstract void fireDisconnectedEvent();
void fireDisconnectedEvent();
public abstract void addListener(IConnectionListener listener);
void fireTimeOutEvent();
public abstract void removeListener(IConnectionListener listener);
void addListener(IConnectionListener listener);
void removeListener(IConnectionListener listener);
}

View File

@ -4,10 +4,12 @@ import java.util.EventListener;
public interface IConnectionListener extends EventListener {
public abstract void onMessageReceivedEvent(String msg);
void onMessageReceivedEvent(String msg);
public abstract void onConnectedEvent();
void onConnectedEvent();
public abstract void onDisconnectedEvent();
void onDisconnectedEvent();
void onTimeOutEvent();
}

View File

@ -1,49 +1,67 @@
package com.pqt.client.module.connection.listeners;
//TODO écrire contenu méthodes
//TODO écrire javadoc
import javax.swing.event.EventListenerList;
import java.util.Arrays;
public class SimpleConnectionFirerer implements IConnectionFirerer {
private EventListenerList listenerList;
public SimpleConnectionFirerer() {
listenerList = new EventListenerList();
}
/**
* @see com.pqt.client.module.connection.listeners.IConnectionFirerer#fireMessageReceivedEvent(String)
*
*
*
*/
@Override
public void fireMessageReceivedEvent(String msg) {
Arrays.stream(listenerList.getListeners(IConnectionListener.class)).forEach(listener->listener.onMessageReceivedEvent(msg));
}
/**
* @see com.pqt.client.module.connection.listeners.IConnectionFirerer#fireConnectedEvent()
*/
@Override
public void fireConnectedEvent() {
Arrays.stream(listenerList.getListeners(IConnectionListener.class)).forEach(IConnectionListener::onConnectedEvent);
}
/**
* @see com.pqt.client.module.connection.listeners.IConnectionFirerer#fireDisconnectedEvent()
*/
@Override
public void fireDisconnectedEvent() {
Arrays.stream(listenerList.getListeners(IConnectionListener.class)).forEach(IConnectionListener::onDisconnectedEvent);
}
/**
* @see com.pqt.client.module.connection.listeners.IConnectionFirerer#fireTimeOutEvent()
*/
@Override
public void fireTimeOutEvent() {
Arrays.stream(listenerList.getListeners(IConnectionListener.class)).forEach(IConnectionListener::onDisconnectedEvent);
}
/**
/**
* @see com.pqt.client.module.connection.listeners.IConnectionFirerer#addListener(com.pqt.client.module.connection.listeners.IConnectionListener)
*/
@Override
public void addListener(IConnectionListener listener) {
listenerList.add(IConnectionListener.class, listener);
}
/**
* @see com.pqt.client.module.connection.listeners.IConnectionFirerer#removeListener(com.pqt.client.module.connection.listeners.IConnectionListener)
*/
@Override
public void removeListener(IConnectionListener listener) {
listenerList.remove(IConnectionListener.class, listener);
}
}

View File

@ -0,0 +1,53 @@
package com.pqt.client.module.connection.senders;
import com.pqt.client.module.connection.listeners.IConnectionListener;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class HttpTextSender implements ITextSender{
@Override
public void send(String url, String text, IConnectionListener listener) {
try {
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Content-Type", "application/json");
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
con.setInstanceFollowRedirects(true);
String params = URLEncoder.encode("message="+text, "UTF-8");
con.setDoOutput(true);
try(DataOutputStream out = new DataOutputStream(con.getOutputStream())) {
out.writeBytes(params);
out.flush();
}
con.connect();
listener.onConnectedEvent();
try(BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()))) {
StringBuilder content = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
listener.onMessageReceivedEvent(content.toString());
}
con.disconnect();
}catch (java.net.SocketTimeoutException e){
listener.onTimeOutEvent();
}catch (IOException e) {
e.printStackTrace();
}finally {
listener.onDisconnectedEvent();
}
}
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.module.connection.senders;
import com.pqt.client.module.connection.listeners.IConnectionListener;
public interface ITextSender {
void send(String url, String text, IConnectionListener listener);
}

View File

@ -0,0 +1,140 @@
package com.pqt.client.module.network;
import com.pqt.client.module.connection.ConnectionService;
import com.pqt.client.module.network.listeners.INetworkServiceListener;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.client.module.query.query_callback.IMapItemMessageCallback;
import com.pqt.client.module.query.query_callback.INoItemMessageCallback;
import com.pqt.core.entities.server_config.ConfigFields;
import com.pqt.core.entities.server_config.ServerConfig;
import javax.swing.event.EventListenerList;
import java.util.*;
//TODO ajout javadoc
/*
* Ce service doit permettre de faire des ping et de récupérer la config d'un serveur distant
*/
public class NetworkService {
private final QueryExecutor queryExecutor;
private final ConnectionService connectionService;
private final EventListenerList listenerList;
private final ServerConfigCache configCache;
public NetworkService(QueryExecutor queryExecutor, ConnectionService connectionService) {
this.queryExecutor = queryExecutor;
this.connectionService = connectionService;
listenerList = new EventListenerList();
configCache = new ServerConfigCache();
}
public void addListener(INetworkServiceListener l){
listenerList.add(INetworkServiceListener.class, l);
}
public void removeListener(INetworkServiceListener l){
listenerList.remove(INetworkServiceListener.class, l);
}
public void sendPQTPing(String host, Integer port){
checkData(host, port);
queryExecutor.executePingQuery(new INoItemMessageCallback() {
@Override
public void ack() {
Arrays.stream(listenerList.getListeners(INetworkServiceListener.class))
.forEach(l->l.onPQTPingSuccessEvent(host, port));
sendConfigRequest(host, port);
}
@Override
public void err(Throwable cause) {
Arrays.stream(listenerList.getListeners(INetworkServiceListener.class))
.forEach(l->l.onPQTPingFailureEvent(host, port, cause));
}
@Override
public void ref(Throwable cause) {
Arrays.stream(listenerList.getListeners(INetworkServiceListener.class))
.forEach(l->l.onPQTPingFailureEvent(host, port, cause));
}
});
}
public boolean hasServerConfig(String host, Integer port){
checkData(host, port);
return configCache.hasConfig(host, port);
}
public ServerConfig getServerConfig(String host, Integer port){
checkData(host, port);
return configCache.getConfig(host, port);
}
public void setActiveServer(String host, Integer port){
connectionService.setServerUrl(String.format("%s:%s", host, port));
}
private void sendConfigRequest(String host, Integer port){
queryExecutor.executeConfigListQuery(new IMapItemMessageCallback<String, String>(){
@Override
public void err(Throwable cause) {
//TODO ajouter log erreur
}
@Override
public void ref(Throwable cause) {
//TODO ajouter log erreur
}
@Override
public void ack(Map<String, String> obj) {
configCache.addServerConfig(host, port, convertToServerConfig(obj));
Arrays.stream(listenerList.getListeners(INetworkServiceListener.class))
.forEach(INetworkServiceListener::onNewServerConfigData);
}
});
}
private ServerConfig convertToServerConfig(Map<String, String> data){
ServerConfig serverConfig = new ServerConfig();
List<String> allowedFields = new ArrayList<>();
EnumSet.allOf(ConfigFields.class).forEach(e->allowedFields.add(e.name()));
data.keySet()
.stream()
.filter(allowedFields::contains)
.filter(key->isBoolean(data.get(key)))
.forEach(key->serverConfig.add(getMatchingConfigFields(key), Boolean.parseBoolean(data.get(key))));
return serverConfig;
}
private boolean isBoolean(String str){
return str.equals("true") || str.equals("false");
}
private ConfigFields getMatchingConfigFields(String str){
ConfigFields match = null;
EnumSet<ConfigFields> enumSet = EnumSet.allOf(ConfigFields.class);
for(ConfigFields field : enumSet){
if(str.equals(field.name()))
match = field;
}
return match;
}
private void checkData(String host, Integer port){
if(host==null || port == null)
throw new NullPointerException("Null value as server data is not allowed");
if(host.isEmpty())
throw new IllegalArgumentException("host cannot be empty");
if(port<1 || port>65535)
throw new IllegalArgumentException("port number must be an unsigned 16-bit integer (0<n<65536)");
}
}

View File

@ -0,0 +1,77 @@
package com.pqt.client.module.network;
import com.pqt.core.entities.server_config.ServerConfig;
import java.util.HashMap;
import java.util.Map;
public class ServerConfigCache {
private final Map<ServerData, ServerConfig> cache;
public ServerConfigCache() {
cache = new HashMap<>();
}
public void addServerConfig(String host, Integer port, ServerConfig config){
ServerData match = cache.keySet().stream().filter(key->key.getHost().equals(host)&&key.getPort().equals(port)).findFirst().orElse(null);
if(match==null){
cache.put(new ServerData(host, port), config);
}else{
cache.replace(match, config);
}
}
public void removeServerData(String host, Integer port){
ServerData data = new ServerData(host, port);
if(cache.containsKey(data))
cache.remove(data);
}
public boolean hasConfig(String host, Integer port){
return cache.containsKey(new ServerData(host, port));
}
public ServerConfig getConfig(String host, Integer port){
if(hasConfig(host, port))
return cache.get(new ServerData(host, port));
return null;
}
private class ServerData{
private String host;
private Integer port;
public ServerData(String host, Integer port) {
this.host = host;
this.port = port;
}
public String getHost() {
return host;
}
public Integer getPort() {
return port;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ServerData that = (ServerData) o;
if (host != null ? !host.equals(that.host) : that.host != null) return false;
return port != null ? port.equals(that.port) : that.port == null;
}
@Override
public int hashCode() {
int result = host != null ? host.hashCode() : 0;
result = 31 * result + (port != null ? port.hashCode() : 0);
return result;
}
}
}

View File

@ -0,0 +1,9 @@
package com.pqt.client.module.network.listeners;
import java.util.EventListener;
public interface INetworkServiceListener extends EventListener {
void onPQTPingSuccessEvent(String host, Integer port);
void onPQTPingFailureEvent(String host, Integer port, Throwable cause);
void onNewServerConfigData();
}

View File

@ -1,35 +1,170 @@
package com.pqt.client.module.query;
import com.pqt.client.module.query.query_callback.IIdQueryCallback;
import com.pqt.core.entities.query.IQuery;
import com.pqt.client.module.query.query_callback.ISimpleQueryCallback;
import com.pqt.client.module.query.query_callback.IStatQueryCallback;
import com.pqt.client.module.query.query_callback.IStockQueryCallback;
import com.pqt.client.module.connection.ConnectionService;
import com.pqt.client.module.connection.listeners.IConnectionListener;
import com.pqt.client.module.query.exceptions.HeaderNotFoundException;
import com.pqt.client.module.query.exceptions.MessageTimeoutException;
import com.pqt.client.module.query.query_callback.*;
import com.pqt.core.communication.GSonMessageToolFactory;
import com.pqt.core.communication.IMessageToolFactory;
import com.pqt.core.entities.messages.Message;
import com.pqt.core.entities.messages.MessageType;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.product.ProductUpdate;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.user_account.Account;
import java.util.List;
//TODO écrire contenu méthodes
//TODO écrire javadoc
public class QueryExecutor {
public static final QueryExecutor INSTANCE = new QueryExecutor();
private QueryExecutor(){
private IMessageToolFactory messageToolFactory;
private ConnectionService connectionService;
private QueryMessageFactory messageFactory;
public QueryExecutor(ConnectionService connectionService){
messageToolFactory = new GSonMessageToolFactory();
this.connectionService = connectionService;
this.messageFactory = new QueryMessageFactory(messageToolFactory);
}
public long execute(IQuery query, ISimpleQueryCallback callback) {
return 0;
}
public long execute(IQuery query, IStatQueryCallback callback) {
return 0;
}
public long execute(IQuery query, IStockQueryCallback callback) {
return 0;
}
public long execute(IQuery query, IIdQueryCallback callback) {
return 0;
public void executeSaleQuery(Sale sale, INoItemMessageCallback callback) {
sendMessage(messageFactory.newSaleMessage(sale), callback, MessageType.ACK_SALE);
}
public void executePingQuery(INoItemMessageCallback callback){
sendMessage(messageFactory.newPingMessage(), callback, MessageType.ACK_PING);
}
public void executeUpdateQuery(List<ProductUpdate> updates, INoItemMessageCallback callback) {
sendMessage(messageFactory.newUpdateMessage(updates), callback, MessageType.ACK_UPDATE);
}
public void executeConnectAccountQuery(Account account, boolean desiredState, INoItemMessageCallback callback){
sendMessage(messageFactory.newConnectAccountMessage(account,desiredState), callback, MessageType.ACK_CONNECT_ACCOUNT);
}
private void sendMessage(Message message, INoItemMessageCallback callback, MessageType responseType){
connectionService.sendText(messageToolFactory.getObjectFormatter(Message.class).format(message), new IConnectionListener() {
@Override
public void onMessageReceivedEvent(String msg) {
Message response = messageToolFactory.getObjectParser(Message.class).parse(msg);
if(response.getType().equals(responseType))
callback.ack();
else
handleUnexpectedTypeInResponse(response, callback);
}
@Override
public void onConnectedEvent() {
}
@Override
public void onDisconnectedEvent() {
}
@Override
public void onTimeOutEvent() {
callback.err(new MessageTimeoutException());
}
});
}
public void executeStockQuery(ICollectionItemMessageCallback<Product> callback) {
sendMessage(messageFactory.newStockMessage(), callback, Product.class, MessageType.MSG_STOCK, "stock");
}
public void executeAccountListQuery(ICollectionItemMessageCallback<Account> callback){
sendMessage(messageFactory.newAccountListMessage(), callback, Account.class, MessageType.MSG_ACCOUNT_LIST, "accounts");
}
private <T> void sendMessage(Message message, ICollectionItemMessageCallback<T> callback, Class<T> clazz, MessageType responseType, String itemHeader){
connectionService.sendText(messageToolFactory.getObjectFormatter(Message.class).format(message), new IConnectionListener() {
@Override
public void onMessageReceivedEvent(String msg) {
Message response = messageToolFactory.getObjectParser(Message.class).parse(msg);
if(response.getType().equals(responseType)) {
String item = response.getField(itemHeader);
if (item != null)
callback.ack(messageToolFactory.getListParser(clazz).parse(item));
else
callback.err(new HeaderNotFoundException("Missing expected header \""+
itemHeader+"\" in response \""+responseType.name()+"\""));
}else
handleUnexpectedTypeInResponse(response, callback);
}
@Override
public void onConnectedEvent() {
}
@Override
public void onDisconnectedEvent() {
}
@Override
public void onTimeOutEvent() {
callback.err(new MessageTimeoutException());
}
});
}
public void executeStatQuery(IMapItemMessageCallback<String, String> callback) {
sendMessage(messageFactory.newStatMessage(), callback, MessageType.MSG_STAT);
}
public void executeConfigListQuery(IMapItemMessageCallback<String, String> callback){
sendMessage(messageFactory.newConfigListMessage(), callback, MessageType.MSG_CONFIG_LIST);
}
//TODO à rendre générique pour toute Map<T, U> au lieu de Map<String, String>
private void sendMessage(Message message, IMapItemMessageCallback<String, String> callback, MessageType responseType){
connectionService.sendText(messageToolFactory.getObjectFormatter(Message.class).format(message), new IConnectionListener() {
@Override
public void onMessageReceivedEvent(String msg) {
Message response = messageToolFactory.getObjectParser(Message.class).parse(msg);
if(response.getType().equals(responseType)){
callback.ack(response.getFields());
}else
handleUnexpectedTypeInResponse(response, callback);
}
@Override
public void onConnectedEvent() {
}
@Override
public void onDisconnectedEvent() {
}
@Override
public void onTimeOutEvent() {
callback.err(new MessageTimeoutException());
}
});
}
private void handleUnexpectedTypeInResponse(Message response, IMessageCallback callback){
switch (response.getType()) {
case ERROR_QUERY:
callback.err(messageToolFactory.getObjectParser(Throwable.class).parse(response.getField("Detail_erreur")));
break;
case REFUSED_QUERY:
callback.ref(messageToolFactory.getObjectParser(Throwable.class).parse(response.getField("Detail_refus")));
break;
default:
callback.err(new IllegalArgumentException(
"Illegal message type for response : " +
"expected \"ACK_SALE\"`, found \"" + response.getType().name() + "\""
));
break;
}
}
}

View File

@ -1,38 +0,0 @@
package com.pqt.client.module.query;
import com.pqt.core.entities.product.ProductUpdate;
import com.pqt.core.entities.query.IQuery;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.user_account.Account;
import java.util.List;
//TODO écrire contenu méthodes
//TODO écrire javadoc
public class QueryFactory {
public static IQuery newConnectQuery(String serverAddress) {
return null;
}
public static IQuery newSaleQuery(Sale sale) {
return null;
}
public static IQuery newStockQuery() {
return null;
}
public static IQuery newStatQuery() {
return null;
}
public static IQuery newLogQuery(Account account, boolean state) {
return null;
}
public static IQuery newUpdateQuery(List<ProductUpdate> updates) {
return null;
}
}

View File

@ -0,0 +1,69 @@
package com.pqt.client.module.query;
import com.pqt.core.communication.IMessageToolFactory;
import com.pqt.core.entities.messages.Message;
import com.pqt.core.entities.messages.MessageType;
import com.pqt.core.entities.product.ProductUpdate;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.user_account.Account;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//TODO écrire javadoc
class QueryMessageFactory {
private final IMessageToolFactory messageToolFactory;
QueryMessageFactory(IMessageToolFactory messageToolFactory) {
this.messageToolFactory = messageToolFactory;
}
Message newSaleMessage(Sale sale) {
Map<String, String> fields = new HashMap<>();
fields.put("sale", messageToolFactory.getObjectFormatter(Sale.class).format(sale));
return newSimpleMessage(MessageType.QUERY_SALE, fields);
}
Message newStockMessage() {
return newSimpleMessage(MessageType.QUERY_STOCK);
}
Message newStatMessage() {
return newSimpleMessage(MessageType.QUERY_STAT);
}
Message newUpdateMessage(List<ProductUpdate> updates) {
Map<String, String> fields = new HashMap<>();
fields.put("updates", messageToolFactory.getListFormatter(ProductUpdate.class).format(updates));
return newSimpleMessage(MessageType.QUERY_UPDATE, fields);
}
Message newAccountListMessage(){
return newSimpleMessage(MessageType.QUERY_ACCOUNT_LIST);
}
Message newConnectAccountMessage(Account account, boolean desiredState){
Map<String, String> fields = new HashMap<>();
fields.put("account", messageToolFactory.getObjectFormatter(Account.class).format(account));
fields.put("desired_state", messageToolFactory.getObjectFormatter(Boolean.class).format(desiredState));
return newSimpleMessage(MessageType.QUERY_CONNECT_ACCOUNT, fields);
}
Message newPingMessage(){
return newSimpleMessage(MessageType.QUERY_PING);
}
Message newConfigListMessage(){
return newSimpleMessage(MessageType.QUERY_CONFIG_LIST);
}
private Message newSimpleMessage(MessageType type, Map<String, String> fields){
return new Message(type, null, null, null, null, fields);
}
private Message newSimpleMessage(MessageType type){
return newSimpleMessage(type, null);
}
}

View File

@ -0,0 +1,19 @@
package com.pqt.client.module.query.exceptions;
public class HeaderNotFoundException extends Exception {
public HeaderNotFoundException() {
super();
}
public HeaderNotFoundException(String message) {
super(message);
}
public HeaderNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public HeaderNotFoundException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,19 @@
package com.pqt.client.module.query.exceptions;
public class MessageTimeoutException extends Exception {
public MessageTimeoutException() {
super();
}
public MessageTimeoutException(String message) {
super(message);
}
public MessageTimeoutException(String message, Throwable cause) {
super(message, cause);
}
public MessageTimeoutException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,6 @@
package com.pqt.client.module.query.query_callback;
import java.util.Collection;
public interface ICollectionItemMessageCallback<T> extends IItemMessageCallback<Collection<T>> {
}

View File

@ -1,7 +0,0 @@
package com.pqt.client.module.query.query_callback;
public interface IIdQueryCallback {
public void ack(long id);
public void err(long id, Throwable cause);
public void ref(long id, Throwable cause);
}

View File

@ -0,0 +1,5 @@
package com.pqt.client.module.query.query_callback;
public interface IItemMessageCallback<T> extends IMessageCallback {
void ack(T obj);
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.module.query.query_callback;
import java.util.Map;
public interface IMapItemMessageCallback<T, U> extends IItemMessageCallback<Map<T, U>> {
}

View File

@ -0,0 +1,6 @@
package com.pqt.client.module.query.query_callback;
public interface IMessageCallback {
void err(Throwable cause);
void ref(Throwable cause);
}

View File

@ -0,0 +1,5 @@
package com.pqt.client.module.query.query_callback;
public interface INoItemMessageCallback extends IMessageCallback {
void ack();
}

View File

@ -1,7 +0,0 @@
package com.pqt.client.module.query.query_callback;
public interface ISimpleQueryCallback {
public void ack();
public void err(Throwable cause);
public void ref(Throwable cause);
}

View File

@ -1,10 +0,0 @@
package com.pqt.client.module.query.query_callback;
import java.util.Map;
public interface IStatQueryCallback {
public void ack(Map<String,String> stats);
public void err(Throwable cause);
public void ref(Throwable cause);
}

View File

@ -1,11 +0,0 @@
package com.pqt.client.module.query.query_callback;
import com.pqt.core.entities.product.Product;
import java.util.List;
public interface IStockQueryCallback {
public void ack(List<Product> products);
public void err(Throwable cause);
public void ref(Throwable cause);
}

View File

@ -1,8 +1,7 @@
package com.pqt.client.module.sale;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.client.module.query.QueryFactory;
import com.pqt.client.module.query.query_callback.IIdQueryCallback;
import com.pqt.client.module.query.query_callback.INoItemMessageCallback;
import com.pqt.client.module.sale.listeners.ISaleFirerer;
import com.pqt.client.module.sale.listeners.ISaleListener;
import com.pqt.client.module.sale.listeners.SimpleSaleFirerer;
@ -14,10 +13,14 @@ import java.util.List;
//TODO add log lines
public class SaleService {
private long saleId;
private ISaleFirerer eventFirerer;
private QueryExecutor executor;
public SaleService() {
public SaleService(QueryExecutor executor) {
saleId = 0;
eventFirerer = new SimpleSaleFirerer();
this.executor = executor;
}
public SaleBuilder getNewSaleBuilder() {
@ -25,22 +28,30 @@ public class SaleService {
}
public long commitSale(SaleBuilder saleBuilder) {
return QueryExecutor.INSTANCE.execute(QueryFactory.newSaleQuery(saleBuilder.build()), new IIdQueryCallback() {
final long currentSaleId = saleId;
if(saleId<Long.MAX_VALUE)
saleId++;
else
saleId = 0;
executor.executeSaleQuery(saleBuilder.build(), new INoItemMessageCallback() {
@Override
public void ack(long id) {
eventFirerer.fireSaleValidationSuccess(id);
public void ack() {
eventFirerer.fireSaleValidationSuccess(currentSaleId);
}
@Override
public void err(long id, Throwable cause) {
eventFirerer.fireSaleValidationError(id, cause);
public void err(Throwable cause) {
eventFirerer.fireSaleValidationError(currentSaleId, cause);
}
@Override
public void ref(long id, Throwable cause) {
eventFirerer.fireSaleValidationRefused(id, cause);
public void ref(Throwable cause) {
eventFirerer.fireSaleValidationRefused(currentSaleId, cause);
}
});
return currentSaleId;
}
/*

View File

@ -1,8 +1,7 @@
package com.pqt.client.module.stat;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.client.module.query.QueryFactory;
import com.pqt.client.module.query.query_callback.IStatQueryCallback;
import com.pqt.client.module.query.query_callback.IMapItemMessageCallback;
import com.pqt.client.module.stat.listeners.IStatFirerer;
import com.pqt.client.module.stat.listeners.IStatListener;
import com.pqt.client.module.stat.listeners.SimpleStatFirerer;
@ -15,11 +14,13 @@ public class StatDao {
private Date lastRefreshTimestamp;
private Map<String, String> stats;
private IStatFirerer eventFirerer;
private QueryExecutor executor;
public StatDao() {
public StatDao(QueryExecutor executor) {
eventFirerer = new SimpleStatFirerer();
stats = new HashMap<>();
lastRefreshTimestamp = null;
this.executor = executor;
}
public synchronized Map<String, String> getStats() {
@ -27,14 +28,7 @@ public class StatDao {
}
public void refreshStats() {
QueryExecutor.INSTANCE.execute(QueryFactory.newStockQuery(), new IStatQueryCallback() {
@Override
public void ack(Map<String, String> stats) {
replaceStats(stats);
eventFirerer.fireGetStatSuccess();
//TODO add log line
}
executor.executeStatQuery(new IMapItemMessageCallback<String, String>() {
@Override
public void err(Throwable cause) {
eventFirerer.fireGetStatError(cause);
@ -46,6 +40,13 @@ public class StatDao {
eventFirerer.fireGetStatRefused(cause);
//TODO add log line
}
@Override
public void ack(Map<String, String> stats) {
replaceStats(stats);
eventFirerer.fireGetStatSuccess();
//TODO add log line
}
});
}

View File

@ -1,5 +1,6 @@
package com.pqt.client.module.stat;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.client.module.stat.listeners.IStatListener;
import java.util.Map;
@ -10,8 +11,8 @@ public class StatService {
private StatDao dao;
public StatService() {
dao = new StatDao();
public StatService(QueryExecutor executor) {
dao = new StatDao(executor);
}
public Map<String,String> getStats() {

View File

@ -1,9 +1,8 @@
package com.pqt.client.module.stock;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.client.module.query.QueryFactory;
import com.pqt.client.module.query.query_callback.IStockQueryCallback;
import com.pqt.client.module.query.query_callback.IIdQueryCallback;
import com.pqt.client.module.query.query_callback.ICollectionItemMessageCallback;
import com.pqt.client.module.query.query_callback.INoItemMessageCallback;
import com.pqt.client.module.stock.Listeners.IStockFirerer;
import com.pqt.client.module.stock.Listeners.IStockListener;
import com.pqt.client.module.stock.Listeners.SimpleStockFirerer;
@ -11,18 +10,22 @@ import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.product.ProductUpdate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Optional;
//TODO écrire javadoc
public class StockDao {
private long updateId;
private IStockFirerer eventFirerer;
private Date lastRefreshTimestamp;
private List<Product> products;
private QueryExecutor executor;
public StockDao() {
public StockDao(QueryExecutor executor) {
this.executor = executor;
updateId = 0;
eventFirerer = new SimpleStockFirerer();
products = new ArrayList<>();
lastRefreshTimestamp = null;
@ -37,9 +40,9 @@ public class StockDao {
}
public void refreshProductList() {
QueryExecutor.INSTANCE.execute(QueryFactory.newStockQuery(), new IStockQueryCallback() {
executor.executeStockQuery(new ICollectionItemMessageCallback<Product>() {
@Override
public void ack(List<Product> products) {
public void ack(Collection<Product> obj) {
replaceProductList(products);
eventFirerer.fireGetProductListSuccessEvent();
//TODO add log line
@ -71,27 +74,33 @@ public class StockDao {
}
public long commitUpdate(List<ProductUpdate> updates){
return QueryExecutor.INSTANCE.execute(QueryFactory.newUpdateQuery(updates),new IIdQueryCallback(){
final long currentUpdateId = updateId;
if(updateId<Long.MAX_VALUE)
updateId++;
else
updateId = 0;
executor.executeUpdateQuery(updates, new INoItemMessageCallback() {
@Override
public void ack(long id) {
public void ack() {
//TODO add log line
refreshProductList();
eventFirerer.fireProductListUpdateSuccessEvent(id);
eventFirerer.fireProductListUpdateSuccessEvent(currentUpdateId);
}
@Override
public void err(long id, Throwable cause) {
//TODO add log line
eventFirerer.fireProductListUpdateErrorEvent(id, cause);
public void err(Throwable cause) {
//TODO add log line
eventFirerer.fireProductListUpdateErrorEvent(currentUpdateId, cause);
}
@Override
public void ref(long id, Throwable cause) {
//TODO add log line
eventFirerer.fireProductListUpdateRefusedEvent(id, cause);
public void ref(Throwable cause) {
//TODO add log line
eventFirerer.fireProductListUpdateRefusedEvent(currentUpdateId, cause);
}
});
return currentUpdateId;
}
/**

View File

@ -1,5 +1,6 @@
package com.pqt.client.module.stock;
import com.pqt.client.module.query.QueryExecutor;
import com.pqt.core.entities.product.Product;
import com.pqt.client.module.stock.Listeners.IStockListener;
@ -9,12 +10,10 @@ import java.util.List;
//TODO Add log lines
public class StockService {
public static final StockService INSTANCE = new StockService();
private StockDao dao;
public StockService() {
dao = new StockDao();
public StockService(QueryExecutor executor) {
dao = new StockDao(executor);
}
/**

View File

@ -2,13 +2,6 @@
-fx-background-color: #1d1d1d;
}
.label {
-fx-font-size: 11pt;
-fx-font-family: "Segoe UI Semibold";
-fx-text-fill: white;
-fx-opacity: 0.8;
}
.label-bright {
-fx-font-size: 11pt;
-fx-font-family: "Segoe UI Semibold";
@ -127,15 +120,32 @@
.context-menu {
-fx-background-color: derive(#1d1d1d,5%);
}
.text-field, .password-field, .choice-box, .text-area, .combo-box, .button {
-fx-font-size: 12pt;
-fx-font-family: "Segoe UI Semibold";
.titled-pane, .titled-pane > .title, .titled-pane > *.content, .text-field,
.password-field, .choice-box, .text-area, .combo-box, .button, .label, .text-displayer {
-fx-font: 12pt "Segoe UI Semibold";
-fx-background-color: #1d1d1d;
-fx-text-fill: #d8d8d8;
}
.text-displayer {
-fx-fill: #d8d8d8;
}
.titled-pane, .titled-pane > .title, .titled-pane > *.content {
-fx-border-width: 0;
}
.text-field, .password-field, .choice-box, .text-area, .combo-box, .button{
-fx-pref-width: 150;
-fx-pref-height: 30;
-fx-background-color: #1d1d1d;
-fx-border-color: #e2e2e2;
-fx-border-width: 2;
-fx-text-fill: #d8d8d8;
}
.label{
-fx-pref-width: 150;
-fx-pref-height: 30;
}
.button:hover {

View File

@ -21,6 +21,5 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
</component>
</module>

View File

@ -1,5 +0,0 @@
package com.pqt.core.entities.query;
public interface IQuery {
}

View File

@ -1,6 +0,0 @@
package com.pqt.core.entities.query;
public enum QueryType {
CONNECT, SALE, STOCK, STAT, LOG, UPDATE
}

View File

@ -1,21 +0,0 @@
package com.pqt.core.entities.query;
import com.pqt.core.entities.sale.Sale;
public class SaleQuery extends SimpleQuery {
private Sale sale;
public SaleQuery(Sale sale) {
super(QueryType.SALE);
this.sale = sale;
}
public Sale getSale() {
return sale;
}
public void setSale(Sale sale) {
this.sale = sale;
}
}

View File

@ -1,21 +0,0 @@
package com.pqt.core.entities.query;
public class SimpleQuery implements IQuery {
private QueryType type;
/**
*
* @param type
* @throws NullPointerException if type is null
*/
public SimpleQuery(QueryType type) {
if(type==null) throw new NullPointerException("null value not allowed as query type");
this.type = type;
}
public QueryType getType() {
return type;
}
}

View File

@ -1,23 +0,0 @@
package com.pqt.core.entities.query;
import com.pqt.core.entities.product.ProductUpdate;
import java.util.List;
public class UpdateQuery extends SimpleQuery {
private List<ProductUpdate> updates;
public UpdateQuery(List<ProductUpdate> updates) {
super(QueryType.UPDATE);
this.updates = updates;
}
public List<ProductUpdate> getUpdates() {
return updates;
}
public void setUpdates(List<ProductUpdate> updates) {
this.updates = updates;
}
}

View File

@ -10,6 +10,7 @@ public class ServerConfig {
private Map<ConfigFields, Boolean> fields;
public ServerConfig() {
fields = new HashMap<>();
}
public ServerConfig(Map<ConfigFields, Boolean> fields) {

View File

@ -25,10 +25,6 @@
<orderEntry type="library" scope="PROVIDED" name="Maven: javax:javaee-api:7.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.sun.mail:javax.mail:1.5.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.activation:activation:1.1" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.4" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: javax:javaee-api:7.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: com.sun.mail:javax.mail:1.5.0" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.activation:activation:1.1" level="project" />
<orderEntry type="module" module-name="core" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.4" level="project" />

View File

@ -1,30 +0,0 @@
package com.pqt.server.tools.security;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5HashTool implements IHashTool{
@Override
public String hashAndSalt(String input, String salt) {
String md5 = null;
if(input == null || salt == null) return null;
try {
String str = salt+input;
//Create MessageDigest object for MD5
MessageDigest digest = MessageDigest.getInstance("MD5");
//Update input string in message digest
digest.update(str.getBytes(), 0, str.length());
//Converts message digest value in base 16 (hex)
md5 = new BigInteger(1, digest.digest()).toString(16);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5;
}
}

View File

@ -5,7 +5,7 @@ import com.pqt.core.entities.user_account.AccountLevel;
import com.pqt.server.tools.io.ISerialFileManager;
import com.pqt.server.tools.io.SimpleSerialFileManagerFactory;
import com.pqt.server.tools.security.IHashTool;
import com.pqt.server.tools.security.MD5HashTool;
import com.pqt.server.tools.security.SHA256HashTool;
import java.util.*;
import java.util.stream.Collectors;
@ -19,7 +19,7 @@ import java.util.stream.Collectors;
* Cette classe n'est pas faite pour gérer les accès concurentiels au fichier assurant la persistance, et n'est donc pas
* thread-safe. Elle est conçue pour que tous les accès soient effectués depuis un même thread et depuis un unique objet.
* <p/>
* Cette classe manipule les mot de passe sous forme chiffrée via un système de hash (md5) + salt, et ne fait pas
* Cette classe manipule les mot de passe sous forme chiffrée via un système de hash (SHA-256) + salt, et ne fait pas
* persister les mots de passes non-chiffrées. Les noms d'utilisateurs sont stockés sans chiffrage.
*/
class FileAccountDao implements IAccountDao {
@ -34,7 +34,7 @@ class FileAccountDao implements IAccountDao {
FileAccountDao() {
accountEntries = new HashSet<>();
connectedAccount = new HashSet<>();
hashTool = new MD5HashTool();
hashTool = new SHA256HashTool();
fileManager = SimpleSerialFileManagerFactory.getFileManager(AccountEntry.class, ACCOUNT_FILE_NAME);
loadFromFile();
}

View File

@ -1,7 +1,6 @@
package com.pqt.server.module.sale;
import com.pqt.core.entities.sale.Sale;
import com.pqt.server.exception.ServerQueryException;
import com.pqt.server.module.sale.listeners.ISaleFirerer;
import com.pqt.server.module.sale.listeners.ISaleListener;
import com.pqt.server.module.sale.listeners.SimpleSaleFirerer;

View File

@ -4,8 +4,6 @@ import com.pqt.core.entities.members.DataServer;
import com.pqt.core.entities.server_config.ConfigFields;
import com.pqt.core.entities.server_config.ServerConfig;
import java.util.Date;
/**
* Cette classe correspond au service interne du serveur, chargé de conserver les données propres au serveur, comme
* son adresse IP ou encore les différents aspects de la configuration actuelle. Il permet également de récupérer un

View File

@ -3,12 +3,10 @@ package com.pqt.server.module.statistics;
import com.pqt.core.entities.product.LightweightProduct;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import com.pqt.server.module.sale.listeners.ISaleListener;
import com.pqt.server.module.sale.listeners.SaleListenerAdapter;
import com.pqt.server.module.stock.StockService;
import com.pqt.server.module.sale.SaleService;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

View File

@ -4,7 +4,6 @@ import com.pqt.core.entities.product.Product;
import com.pqt.server.tools.entities.SaleContent;
import java.util.List;
import java.util.Map;
/**
* Interface définissant les méthodes requises pour tout DAO du service de gestion des commandes {@link StockService}.

View File

@ -6,7 +6,6 @@ import com.pqt.server.exception.ServerQueryException;
import com.pqt.server.tools.entities.SaleContent;
import java.util.List;
import java.util.Map;
//TODO ajouter logs

Some files were not shown because too many files have changed in this diff Show More