Commit b823641e authored by Administrator's avatar Administrator

Initial commit

parents
#Eclipse
.settings
.project
.classpath
#Maven
target
#General
bak
This diff is collapsed.
# Kata 3: JDBC
En esta Kata utilizaremos JDBC para trabajar con una base de datos, partiendo del siguiente proyecto base: https://sing-group.org/dt/gitlab/dai-2324/kata3-base
Este proyecto contiene un sistema funcional para la gestión de datos de usuarios. El único problema de este sistema es que el almacenamiento de datos realizado por la clase `EmployeesMapDAO` se realiza en memoria, con lo que el sistema no resulta realmente útil.
El objetivo de esta Kata será sustituir la clase `EmployeesMapDAO` por otra llamada `EmployeesDBDAO` que almacene los datos en una base de datos a través de JDBC.
Aunque al principio del Kata se explicará brevemente la estructura del programa, tan solo será necesario crear y editar la clase `EmployeesDBDAO`. Por lo tanto, no será necesario modificar ninguna otra clase, con la excepción de la clase `Launcher` (ver indicaciones en la misma clase) una vez completada la clase `EmployeesDBDAO`.
## Notas
1. La aplicación se puede ejecutar lanzando la clase `es.uvigo.esei.dai.kata3.Launch` o, simplemente, ejecutando el comando `mvn exec:java` desde la raíz del proyecto.
2. Cuando se haya completado la Kata se probará contra dos bases de datos:
* **JavaDB** / **Derby**: es un SGBD ligero y embebible, diseñado, principalmente, para pruebas. En el proyecto tendrás una base de datos Derby en el directorio `db` y las consultas de creación de las tablas en `sql/employees.javadb.sql`. En principio, no debería ser necesario que las ejecutes manualmente, puesto que la tabla ya debería estar creada en la base de datos.
* **MySQL**: en el fichero `sql/employees.mysql.sql` están las consultas necesarias para crear las base de datos. La base de datos se llamará `employees` y debe tener acceso a ella el usuario `kata3` con password `kata3`.
# *************************************************************************
# *** DO NOT TOUCH FILES IN THIS DIRECTORY! ***
# *** FILES IN THIS DIRECTORY AND SUBDIRECTORIES CONSTITUTE A DERBY ***
# *** DATABASE, WHICH INCLUDES THE DATA (USER AND SYSTEM) AND THE ***
# *** FILES NECESSARY FOR DATABASE RECOVERY. ***
# *** EDITING, ADDING, OR DELETING ANY OF THESE FILES MAY CAUSE DATA ***
# *** CORRUPTION AND LEAVE THE DATABASE IN A NON-RECOVERABLE STATE. ***
# *************************************************************************
\ No newline at end of file
# *************************************************************************
# *** DO NOT TOUCH FILES IN THIS DIRECTORY! ***
# *** FILES IN THIS DIRECTORY ARE USED BY THE DERBY DATABASE RECOVERY ***
# *** SYSTEM. EDITING, ADDING, OR DELETING FILES IN THIS DIRECTORY ***
# *** WILL CAUSE THE DERBY RECOVERY SYSTEM TO FAIL, LEADING TO ***
# *** NON-RECOVERABLE CORRUPT DATABASES. ***
# *************************************************************************
\ No newline at end of file
# *************************************************************************
# *** DO NOT TOUCH FILES IN THIS DIRECTORY! ***
# *** FILES IN THIS DIRECTORY ARE USED BY THE DERBY DATABASE TO STORE ***
# *** USER AND SYSTEM DATA. EDITING, ADDING, OR DELETING FILES IN THIS ***
# *** DIRECTORY WILL CORRUPT THE ASSOCIATED DERBY DATABASE AND MAKE ***
# *** IT NON-RECOVERABLE. ***
# *************************************************************************
\ No newline at end of file
#/home/michi/git/dai-katas/Kata3/db/employees
# ********************************************************************
# *** Please do NOT edit this file. ***
# *** CHANGING THE CONTENT OF THIS FILE MAY CAUSE DATA CORRUPTION. ***
# ********************************************************************
#Tue Oct 03 13:15:58 CEST 2023
SysconglomeratesIdentifier=32
SyscolumnsIdentifier=144
derby.serviceLocale=en_US
SystablesIdentifier=96
SysconglomeratesIndex3Identifier=81
derby.storage.propertiesId=16
derby.serviceProtocol=org.apache.derby.database.Database
SyscolumnsIndex1Identifier=161
SysschemasIndex2Identifier=225
SystablesIndex2Identifier=129
SyscolumnsIndex2Identifier=177
SysconglomeratesIndex2Identifier=65
SysschemasIndex1Identifier=209
SysschemasIdentifier=192
SystablesIndex1Identifier=113
SysconglomeratesIndex1Identifier=49
#--- last line, don't put anything after this line ---
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>es.uvigo.esei.dai</groupId>
<artifactId>kata3</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>DAI Dojo - Código base Kata 3</name>
<inceptionYear>2014</inceptionYear>
<url>https://sing-group.org/dt/gitlab/dai-2324/kata3-base</url>
<developers>
<developer>
<name>Miguel Reboiro-Jato</name>
<organization>Escola Superior de Enxeñaría Informática -
Universidade de Vigo</organization>
<organizationUrl>https://esei.uvigo.es/</organizationUrl>
<email>mrjato@uvigo.gal</email>
</developer>
</developers>
<licenses>
<license>
<name>GNU GENERAL PUBLIC LICENSE, Version 3</name>
<url>http://www.gnu.org/licenses/gpl.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Dependencies versions -->
<mysql-connector-j.version>8.1.0</mysql-connector-j.version>
<derby.version>10.15.2.0</derby.version>
<!-- Plugin versions -->
<license-maven-plugin.version>2.2.0</license-maven-plugin.version>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<exec-maven-plugin.version>3.1.0</exec-maven-plugin.version>
<!-- license-maven-plugin configuration -->
<license.licenseName>gpl_v3</license.licenseName>
<license.copyrightOwners>Miguel Reboiro Jato</license.copyrightOwners>
<license.organizationName>Universidade de Vigo</license.organizationName>
<license.addJavaLicenseAfterPackage>false</license.addJavaLicenseAfterPackage>
</properties>
<contributors>
<contributor>
<name>Miguel Reboiro Jato</name>
<email>mrjato@uvigo.gal</email>
<organization>Escola Superior de Enxeñaría Informática -
Universidade de Vigo</organization>
<organizationUrl>https://esei.uvigo.es/</organizationUrl>
<roles>
<role>author</role>
<role>professor</role>
</roles>
</contributor>
</contributors>
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql-connector-j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>${derby.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>${license-maven-plugin.version}</version>
<executions>
<execution>
<id>first</id>
<goals>
<goal>update-file-header</goal>
</goals>
<phase>process-sources</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${exec-maven-plugin.version}</version>
<configuration>
<mainClass>es.uvigo.esei.dai.kata3.Launch</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
DROP TABLE Employees;
CREATE TABLE Employees (
id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
name VARCHAR(100) NOT NULL,
surname VARCHAR(100) NOT NULL,
birth DATE NOT NULL,
salary INTEGER NOT NULL,
intern BOOLEAN NOT NULL,
PRIMARY KEY (id)
);
CREATE DATABASE IF NOT EXISTS `employees`;
USE `employees`;
DROP TABLE IF EXISTS Employees;
CREATE TABLE `employees`.`Employees` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(100) NULL ,
`surname` VARCHAR(100) NULL ,
`birth` DATE NULL ,
`salary` INT NULL ,
`intern` BIT NULL ,
PRIMARY KEY (`id`)
);
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3;
public class EmployeeNotFoundException extends Exception {
private static final long serialVersionUID = 1L;
private final int id;
public EmployeeNotFoundException(int id) {
this.id = id;
}
public EmployeeNotFoundException(String message, int id) {
super(message);
this.id = id;
}
public EmployeeNotFoundException(Throwable cause, int id) {
super(cause);
this.id = id;
}
public EmployeeNotFoundException(String message, Throwable cause, int id) {
super(message, cause);
this.id = id;
}
public EmployeeNotFoundException(
String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, int id
) {
super(message, cause, enableSuppression, writableStackTrace);
this.id = id;
}
public int getId() {
return this.id;
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import es.uvigo.esei.dai.kata3.controller.DefaultEmployeesController;
import es.uvigo.esei.dai.kata3.controller.EmployeesController;
import es.uvigo.esei.dai.kata3.model.dao.EmployeesDAO;
import es.uvigo.esei.dai.kata3.model.dao.EmployeesMapDAO;
import es.uvigo.esei.dai.kata3.view.EmployeesPanel;
public class Launch {
public static void main(String[] args) throws SQLException {
// Una vez completado el ejercicio cambiar el DAO creado
final EmployeesDAO dao = new EmployeesMapDAO();
// final EmployeesDAO dao = createEmployeesJavaDBDAO(false);
// final EmployeesDAO dao = createEmployeesMySQLDBDAO();
final EmployeesController controller = new DefaultEmployeesController(dao);
SwingUtilities.invokeLater(() -> {
changeLookAndFeelToNimbus();
final JFrame frame = new JFrame("Employees Manager");
frame.setContentPane(new EmployeesPanel(controller));
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
/* Una vez completado el ejercicio descomentar este bloque de código.
private final static EmployeesDAO createEmployeesJavaDBDAO(boolean createDatabase) throws SQLException {
final Connection connection;
// La base de datos ya debería estar creada
if (createDatabase) {
connection = DriverManager.getConnection("jdbc:derby:db/employees;create=true", "kata3", "kata3");
createJavaDBDatabase(connection);
} else {
connection = DriverManager.getConnection("jdbc:derby:db/employees", "kata3", "kata3");
}
return new EmployeesDBDAO(connection);
}
private final static void createJavaDBDatabase(Connection connection) throws SQLException {
connection.createStatement().execute("CREATE SCHEMA KATA3");
connection.createStatement().execute(
"CREATE TABLE Employees "
+ "(id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
+ "name VARCHAR(100) NOT NULL, "
+ "surname VARCHAR(100) NOT NULL, "
+ "birth DATE NOT NULL, "
+ "salary INTEGER NOT NULL, "
+ "intern BOOLEAN NOT NULL, PRIMARY KEY (id)"
+ ")"
);
}
private final static EmployeesDAO createEmployeesMySQLDBDAO() throws SQLException {
final Connection connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/employees", "kata3", "kata3");
return new EmployeesDBDAO(connection);
}*/
private static void changeLookAndFeelToNimbus() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// If Nimbus is not available, you can set the GUI to another
// look and feel.
}
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3;
public enum SearchType {
NAME("Name"),
SURNAME("Surname"),
SALARY("Salary");
private final String label;
private SearchType(String label) {
this.label = label;
}
@Override
public String toString() {
return this.label;
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.controller;
import java.util.List;
import es.uvigo.esei.dai.kata3.EmployeeNotFoundException;
import es.uvigo.esei.dai.kata3.SearchType;
import es.uvigo.esei.dai.kata3.model.dao.EmployeesDAO;
import es.uvigo.esei.dai.kata3.model.entity.Employee;
public class DefaultEmployeesController implements EmployeesController {
private final EmployeesDAO dao;
public DefaultEmployeesController(EmployeesDAO dao) {
this.dao = dao;
}
@Override
public Employee get(int id) throws EmployeeNotFoundException {
return this.dao.get(id);
}
@Override
public void create(Employee employee) {
this.dao.create(employee);
}
@Override
public void update(Employee employee) throws EmployeeNotFoundException {
this.dao.update(employee);
}
@Override
public void delete(int id) throws EmployeeNotFoundException {
this.dao.delete(id);
}
@Override
public List<Employee> list() {
return this.dao.list();
}
@Override
public List<Employee> list(SearchType type, String value) throws IllegalArgumentException {
switch (type) {
case NAME:
return this.dao.listByName(value);
case SURNAME:
return this.dao.listBySurname(value);
case SALARY:
try {
return this.dao.listBySalary(Integer.parseInt(value));
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException(nfe);
}
default:
throw new IllegalArgumentException("Unknown type: " + type);
}
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.controller;
import java.util.List;
import es.uvigo.esei.dai.kata3.EmployeeNotFoundException;
import es.uvigo.esei.dai.kata3.SearchType;
import es.uvigo.esei.dai.kata3.model.entity.Employee;
public interface EmployeesController {
public void create(Employee employee);
public void update(Employee employee) throws EmployeeNotFoundException;
public void delete(int id) throws EmployeeNotFoundException;
public Employee get(int id) throws EmployeeNotFoundException;
public List<Employee> list();
public List<Employee> list(SearchType type, String value) throws IllegalArgumentException;
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.model.dao;
import java.util.List;
import es.uvigo.esei.dai.kata3.EmployeeNotFoundException;
import es.uvigo.esei.dai.kata3.model.entity.Employee;
public interface EmployeesDAO {
public void create(Employee employee); // Debe asignársele a employee el id generado
public void update(Employee employee) throws EmployeeNotFoundException;
public void delete(int id) throws EmployeeNotFoundException;
public Employee get(int id) throws EmployeeNotFoundException;
public List<Employee> list();
public List<Employee> listByName(String name);
public List<Employee> listBySurname(String surname);
public List<Employee> listBySalary(int minimumSalary);
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.model.dao;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import es.uvigo.esei.dai.kata3.EmployeeNotFoundException;
import es.uvigo.esei.dai.kata3.model.entity.Employee;
public class EmployeesMapDAO implements EmployeesDAO {
private final Map<Integer, Employee> employees;
private int idGenerator;
public EmployeesMapDAO() {
this.employees = new HashMap<>();
final Calendar calendar = GregorianCalendar.getInstance();
this.idGenerator = 1;
calendar.set(1980, Calendar.FEBRUARY, 10);
this.create(new Employee("Manuel", "Martínez", calendar.getTime(), 10000, false));
calendar.set(1975, Calendar.MARCH, 21);
this.create(new Employee("María", "Muñíz", calendar.getTime(), 12000, true));
}
@Override
public Employee get(int id) throws EmployeeNotFoundException {
if (this.employees.containsKey(id)) {
return this.employees.get(id);
} else {
throw new EmployeeNotFoundException(id);
}
}
@Override
public void create(Employee employee) {
employee.setId(this.idGenerator++);
this.employees.put(employee.getId(), employee);
}
@Override
public void update(Employee employee) throws EmployeeNotFoundException {
System.out.println(employee);
System.out.println(this.employees);
if (this.employees.containsKey(employee.getId())) {
this.employees.put(employee.getId(), employee);
System.out.println(this.employees);
} else {
throw new EmployeeNotFoundException(employee.getId());
}
}
@Override
public void delete(int id) throws EmployeeNotFoundException {
if (this.employees.remove(id) == null) {
throw new EmployeeNotFoundException(id);
}
}
@Override
public List<Employee> list() {
return new ArrayList<>(this.employees.values());
}
@Override
public List<Employee> listByName(String name) {
final List<Employee> employees = this.list();
final Iterator<Employee> itEmployees = employees.iterator();
while (itEmployees.hasNext()) {
if (!itEmployees.next().getName().contains(name)) {
itEmployees.remove();
}
}
return employees;
}
@Override
public List<Employee> listBySurname(String surname) {
final List<Employee> employees = this.list();
final Iterator<Employee> itEmployees = employees.iterator();
while (itEmployees.hasNext()) {
if (!itEmployees.next().getSurname().contains(surname)) {
itEmployees.remove();
}
}
return employees;
}
@Override
public List<Employee> listBySalary(int minimumSalary) {
final List<Employee> employees = this.list();
final Iterator<Employee> itEmployees = employees.iterator();
while (itEmployees.hasNext()) {
if (itEmployees.next().getSalary() < minimumSalary) {
itEmployees.remove();
}
}
return employees;
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.model.entity;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String surname;
private int salary;
private Date birth;
private boolean intern;
public Employee() {
}
public Employee(String name, String surname, Date birth, int salary, boolean intern) {
this.name = name;
this.surname = surname;
this.salary = salary;
this.birth = birth;
this.intern = intern;
}
public Employee(Integer id, String name, String surname, Date birth, int salary, boolean intern) {
this.id = id;
this.name = name;
this.surname = surname;
this.birth = birth;
this.salary = salary;
this.intern = intern;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public boolean isIntern() {
return intern;
}
public void setIntern(boolean intern) {
this.intern = intern;
}
@Override
public int hashCode() {
return Objects.hash(birth, id, intern, name, salary, surname);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
return Objects.equals(birth, other.birth) && Objects.equals(id, other.id) && intern == other.intern
&& Objects.equals(name, other.name) && salary == other.salary && Objects.equals(surname, other.surname);
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", surname=" + surname + ", salary=" + salary + ", birth=" + birth
+ ", intern=" + intern + "]";
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.view;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import es.uvigo.esei.dai.kata3.EmployeeNotFoundException;
import es.uvigo.esei.dai.kata3.model.entity.Employee;
public class EmployeesDataPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final EmployeesMediator mediator;
private final JTextField txtName;
private final JTextField txtSurname;
private final JFormattedTextField ftxtSalary;
private final JFormattedTextField ftxtBirth;
private final JCheckBox chkIntern;
private final JButton btnSaveOrUpdate;
private final JButton btnDelete;
private final JButton btnReset;
private Employee employee;
public EmployeesDataPanel(EmployeesMediator mediator) {
super(new FlowLayout(FlowLayout.LEADING));
this.mediator = mediator;
// Header
final JLabel lblHeader = new JLabel("Employee Data");
lblHeader.setFont(lblHeader.getFont().deriveFont(Font.BOLD));
lblHeader.setHorizontalTextPosition(JLabel.CENTER);
// End Header
// Form
this.txtName = new JTextField();
this.txtName.setPreferredSize(new Dimension(200, (int) this.txtName.getPreferredSize().getHeight()));
this.txtSurname = new JTextField();
this.ftxtSalary = new JFormattedTextField(NumberFormat.getIntegerInstance());
this.ftxtBirth = new JFormattedTextField(new SimpleDateFormat("dd/MM/yyyy"));
this.chkIntern = new JCheckBox();
final String[] labels = new String[] { "Name", "Surname", "Salary", "Birth", "Is intern?" };
final JComponent[] components = new JComponent[] { this.txtName, this.txtSurname, this.ftxtSalary, this.ftxtBirth,
this.chkIntern };
final JPanel panelData = new JPanel(new SpringLayout());
final ValidateFocusAdapter validator = new ValidateFocusAdapter();
for (int i = 0; i < labels.length; i++) {
final JLabel label = new JLabel(labels[i]);
label.setLabelFor(components[i]);
panelData.add(label);
panelData.add(components[i]);
components[i].addFocusListener(validator);
}
SpringUtilities.makeCompactGrid(panelData, 5, 2, 6, 6, 6, 6);
// End Form
// Buttons
final JPanel panelButtons = new JPanel();
this.btnSaveOrUpdate = new JButton(new ActionSaveOrUpdate());
this.btnReset = new JButton(new ActionReset());
this.btnDelete = new JButton(new ActionDelete());
panelButtons.add(this.btnSaveOrUpdate);
panelButtons.add(this.btnReset);
panelButtons.add(this.btnDelete);
// End Buttons
final JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.add(lblHeader, BorderLayout.NORTH);
containerPanel.add(panelData, BorderLayout.CENTER);
containerPanel.add(panelButtons, BorderLayout.SOUTH);
this.add(containerPanel);
this.newEmployee();
}
protected void validateFields() {
this.btnSaveOrUpdate.setEnabled(
!(this.txtName.getText().trim().isEmpty() || this.txtSurname.getText().trim().isEmpty()
|| this.ftxtSalary.getText().trim().isEmpty() || this.ftxtBirth.getText().trim().isEmpty())
);
}
public Employee getEmployee() {
this.employee.setName(this.txtName.getText());
this.employee.setSurname(this.txtSurname.getText());
this.employee.setSalary(((Number) this.ftxtSalary.getValue()).intValue());
this.employee.setBirth((Date) this.ftxtBirth.getValue());
this.employee.setIntern(this.chkIntern.isSelected());
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
this.txtName.setText(this.employee.getName());
this.txtSurname.setText(this.employee.getSurname());
this.ftxtSalary.setValue(this.employee.getSalary());
this.ftxtBirth.setValue(this.employee.getBirth());
this.chkIntern.setSelected(this.employee.isIntern());
if (this.isNewEmployee()) {
this.btnSaveOrUpdate.setText("Save");
this.btnDelete.setEnabled(false);
} else {
this.btnSaveOrUpdate.setText("Update");
this.btnDelete.setEnabled(true);
}
this.validateFields();
}
public void newEmployee() {
this.setEmployee(new Employee());
}
private boolean isNewEmployee() {
return this.employee.getId() == null;
}
private final class ValidateFocusAdapter extends FocusAdapter {
@Override
public void focusLost(FocusEvent e) {
EmployeesDataPanel.this.validateFields();
}
}
private final class ActionDelete extends AbstractAction {
private static final long serialVersionUID = 1L;
private ActionDelete() {
super("Delete");
}
@Override
public void actionPerformed(ActionEvent e) {
try {
EmployeesDataPanel.this.mediator.deleteEmployee(EmployeesDataPanel.this.employee);
} catch (EmployeeNotFoundException e1) {
JOptionPane.showMessageDialog(
EmployeesDataPanel.this, "Error al eliminar el empleado. Identificador desconocido", "Error",
JOptionPane.ERROR_MESSAGE
);
}
}
}
private final class ActionReset extends AbstractAction {
private static final long serialVersionUID = 1L;
private ActionReset() {
super("Reset");
}
@Override
public void actionPerformed(ActionEvent e) {
EmployeesDataPanel.this.setEmployee(EmployeesDataPanel.this.employee);
}
}
private final class ActionSaveOrUpdate extends AbstractAction {
private static final long serialVersionUID = 1L;
private ActionSaveOrUpdate() {
super("Save");
}
@Override
public void actionPerformed(ActionEvent e) {
if (EmployeesDataPanel.this.isNewEmployee()) {
EmployeesDataPanel.this.mediator.createEmployee(EmployeesDataPanel.this.getEmployee());
} else {
try {
EmployeesDataPanel.this.mediator.updateEmployee(EmployeesDataPanel.this.getEmployee());
} catch (EmployeeNotFoundException e1) {
JOptionPane.showMessageDialog(
EmployeesDataPanel.this, "Error al actualizar los datos del empleado. Identificador desconocido", "Error",
JOptionPane.ERROR_MESSAGE
);
}
}
}
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.view;
import java.util.List;
import javax.swing.JTable;
import javax.swing.JTextField;
import es.uvigo.esei.dai.kata3.EmployeeNotFoundException;
import es.uvigo.esei.dai.kata3.SearchType;
import es.uvigo.esei.dai.kata3.controller.EmployeesController;
import es.uvigo.esei.dai.kata3.model.entity.Employee;
import es.uvigo.esei.dai.kata3.view.EmployeesPanel.EmployeeTableModel;
class EmployeesMediator {
private final EmployeesController controller;
private EmployeesDataPanel dataPanel;
private JTable table;
private JTextField txtSearch;
public EmployeesMediator(EmployeesController controller) {
this.controller = controller;
}
public void setDataPanel(EmployeesDataPanel dataPanel) {
this.dataPanel = dataPanel;
}
public void setTable(JTable table) {
this.table = table;
}
public void setTxtSearch(JTextField txtSearch) {
this.txtSearch = txtSearch;
}
public void newEmployee() {
this.dataPanel.newEmployee();
this.table.clearSelection();
}
public void createEmployee(Employee employee) {
this.controller.create(employee);
this.clearSearch();
this.dataPanel.setEmployee(employee);
this.selectEmployee(employee);
}
public void editEmployee(Employee employee) {
this.dataPanel.setEmployee(employee);
}
public void updateEmployee(Employee employee) throws EmployeeNotFoundException {
this.controller.update(employee);
this.clearSearch();
this.dataPanel.setEmployee(employee);
this.selectEmployee(employee);
}
public void deleteEmployee(Employee employee) throws EmployeeNotFoundException {
this.controller.delete(employee.getId());
this.clearSearch();
this.table.clearSelection();
this.dataPanel.newEmployee();
}
public void clearSearch() {
this.search(null, null);
this.txtSearch.setText("");
}
public void search(SearchType type, String value) {
final List<Employee> employees;
if (value == null || value.trim().isEmpty()) {
employees = this.controller.list();
} else {
employees = this.controller.list(type, value.trim());
}
this.updateEmployeeList(employees);
this.dataPanel.newEmployee();
}
private void updateEmployeeList(final List<Employee> employees) {
((EmployeeTableModel) this.table.getModel()).setEmployees(employees);
}
private void selectEmployee(final Employee employee) {
final EmployeeTableModel model = (EmployeeTableModel) this.table.getModel();
final int index = model.indexOf(employee);
if (index >= 0) {
this.table.setRowSelectionInterval(index, index);
}
}
}
/*-
* #%L
* DAI Dojo - Código base Kata 3
* %%
* Copyright (C) 2014 - 2023 Miguel Reboiro Jato
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
package es.uvigo.esei.dai.kata3.view;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import es.uvigo.esei.dai.kata3.SearchType;
import es.uvigo.esei.dai.kata3.controller.EmployeesController;
import es.uvigo.esei.dai.kata3.model.entity.Employee;
public class EmployeesPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final JButton btnNewEmployee;
private final JTextField txtSearch;
private final JComboBox<SearchType> cmbSearchType;
private final JButton btnSearch;
private final JButton btnClear;
private final JTable tableEmployees;
private final EmployeesDataPanel dataPanel;
private final EmployeesMediator mediator;
public EmployeesPanel(EmployeesController controller) {
super(new BorderLayout());
this.mediator = new EmployeesMediator(controller);
// TOP Panel
this.txtSearch = new JTextField();
this.cmbSearchType = new JComboBox<>(SearchType.values());
this.cmbSearchType.setSelectedIndex(0);
this.btnSearch = new JButton(new ActionSearch());
this.btnClear = new JButton(new ActionClear());
this.btnNewEmployee = new JButton(new ActionNewEmployee());
this.mediator.setTxtSearch(this.txtSearch);
final JPanel panelTop = new JPanel(new BorderLayout(10, 4));
final JPanel panelSearchButtons = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
panelSearchButtons.add(this.cmbSearchType);
panelSearchButtons.add(this.btnSearch);
panelSearchButtons.add(this.btnClear);
final JPanel panelSearch = new JPanel(new BorderLayout());
panelSearch.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
panelSearch.add(this.txtSearch, BorderLayout.CENTER);
panelSearch.add(panelSearchButtons, BorderLayout.EAST);
panelTop.add(this.btnNewEmployee, BorderLayout.EAST);
panelTop.add(panelSearch, BorderLayout.CENTER);
// End TOP Panel
// Employees Table
final EmployeeTableModel model = new EmployeeTableModel(controller.list());
this.tableEmployees = new JTable(model);
this.tableEmployees.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.tableEmployees.setRowSelectionAllowed(true);
this.tableEmployees.setColumnSelectionAllowed(false);
this.tableEmployees.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
final int index = EmployeesPanel.this.tableEmployees.getSelectedRow();
if (index >= 0) {
EmployeesPanel.this.mediator.editEmployee(model.getEmployee(index));
}
}
});
this.mediator.setTable(this.tableEmployees);
// End Employees Table
// Employees Data Panel
this.dataPanel = new EmployeesDataPanel(this.mediator);
this.mediator.setDataPanel(this.dataPanel);
// End Employees Data Panel
this.add(panelTop, BorderLayout.NORTH);
this.add(new JScrollPane(this.tableEmployees), BorderLayout.CENTER);
this.add(this.dataPanel, BorderLayout.EAST);
}
final class EmployeeTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private List<Employee> employees;
public EmployeeTableModel(List<Employee> employees) {
this.employees = employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
this.fireTableDataChanged();
}
public Employee getEmployee(int index) {
return this.employees.get(index);
}
public int indexOf(Employee employee) {
if (employee.getId() != null) {
for (int i = 0; i < this.employees.size(); i++) {
if (this.employees.get(i).getId().equals(employee.getId()))
return i;
}
}
return -1;
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public int getRowCount() {
return this.employees.size();
}
@Override
public String getColumnName(int column) {
final String[] columns = new String[] { "Name", "Surname", "Salary" };
return columns[column];
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
final Employee employee = this.employees.get(rowIndex);
switch (columnIndex) {
case 0:
return employee.getName();
case 1:
return employee.getSurname();
case 2:
return employee.getSalary();
default:
return null;
}
}
}
private final class ActionSearch extends AbstractAction {
private static final long serialVersionUID = 1L;
private ActionSearch() {
super("Search");
}
@Override
public void actionPerformed(ActionEvent e) {
try {
EmployeesPanel.this.mediator.search(
(SearchType) EmployeesPanel.this.cmbSearchType.getSelectedItem(), EmployeesPanel.this.txtSearch.getText()
);
} catch (IllegalArgumentException iae) {
JOptionPane
.showMessageDialog(EmployeesPanel.this, "Valor de búsqueda incorrecto", "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
public class ActionClear extends AbstractAction {
private static final long serialVersionUID = 1L;
public ActionClear() {
super("Clear");
}
@Override
public void actionPerformed(ActionEvent e) {
try {
EmployeesPanel.this.mediator.clearSearch();
} catch (IllegalArgumentException iae) {
JOptionPane
.showMessageDialog(EmployeesPanel.this, "Valor de búsqueda incorrecto", "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
private final class ActionNewEmployee extends AbstractAction {
private static final long serialVersionUID = 1L;
private ActionNewEmployee() {
super("New Employee");
}
@Override
public void actionPerformed(ActionEvent e) {
EmployeesPanel.this.mediator.newEmployee();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment