├── .gitignore ├── src └── main │ ├── webapp │ ├── META-INF │ │ ├── MANIFEST.MF │ │ └── context.xml │ └── WEB-INF │ │ └── web.xml │ └── java │ └── com │ └── zufar │ └── testtask │ ├── model │ ├── Priority.java │ ├── Identified.java │ ├── Doctor.java │ ├── Patient.java │ └── Prescription.java │ ├── dao │ ├── CrudDao.java │ ├── ConnectionManager.java │ └── AbstractCrudDao.java │ ├── hsqldb │ ├── DaoFactory.java │ ├── dto │ │ └── PersonFullName.java │ ├── PatientDao.java │ ├── DoctorDao.java │ └── PrescriptionDao.java │ └── ui │ ├── MainUI.java │ ├── window │ ├── AbstractWindow.java │ ├── DoctorWindow.java │ ├── PatientWindow.java │ └── PrescriptionWindow.java │ └── layout │ ├── AbstractVerticalLayout.java │ ├── PatientVerticalLayout.java │ ├── DoctorVerticalLayout.java │ └── PrescriptionVerticalLayout.java ├── db.properties ├── README.md ├── db.script └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target/ 3 | *.iml 4 | *.ipr 5 | *.iws -------------------------------------------------------------------------------- /src/main/webapp/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /src/main/webapp/META-INF/context.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/model/Priority.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.model; 2 | 3 | public enum Priority { 4 | NORMAL, SITO, STATIM; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/model/Identified.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.model; 2 | 3 | public interface Identified { 4 | 5 | Id getId(); 6 | 7 | void setId(Id id); 8 | } -------------------------------------------------------------------------------- /db.properties: -------------------------------------------------------------------------------- 1 | #HSQL Database Engine 2.3.4 2 | #Fri Jul 14 13:23:13 SAMT 2017 3 | version=2.3.4 4 | modified=yes 5 | tx_timestamp=0 6 | readonly=false 7 | files_readonly=true 8 | hsqldb.lock_file=false -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Test Task 2 | ========= 3 | 4 | Prerequisites 5 | ------------- 6 | 7 | * [Java Development Kit (JDK) 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 8 | * [Maven 3](https://maven.apache.org/download.cgi) 9 | 10 | Build and Run 11 | ------------- 12 | 13 | 1. Run in the command line: 14 | ``` 15 | mvn package 16 | mvn jetty:run 17 | ``` 18 | 19 | 2. Open `http://localhost:8080` in a web browser. 20 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/dao/CrudDao.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.dao; 2 | 3 | import com.zufar.testtask.model.Identified; 4 | 5 | import java.sql.SQLException; 6 | import java.util.List; 7 | 8 | public interface CrudDao, Id> { 9 | 10 | /* Создает запись в БД, соответствующую обьекту object */ 11 | void create(E object) throws SQLException; 12 | 13 | /* Возвращает обьект, соответствующий данному идентификатору */ 14 | E get(Id id) throws SQLException; 15 | 16 | /* Возвращает список обьектов, соответствующим всем записям в БД */ 17 | List getAll() throws SQLException; 18 | 19 | /* Изменяет запись в БД в соответствии с состоянием object */ 20 | void update(E object) throws SQLException; 21 | 22 | /* Удаляет запись в БД, соответствующую обьекту object*/ 23 | void delete(E object) throws SQLException; 24 | 25 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/hsqldb/DaoFactory.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.hsqldb; 2 | 3 | import com.zufar.testtask.dao.ConnectionManager; 4 | 5 | import java.sql.SQLException; 6 | 7 | public class DaoFactory { 8 | 9 | private static DaoFactory instance = null; 10 | 11 | private DaoFactory() { 12 | } 13 | 14 | public static DaoFactory getInstance() { 15 | if (instance == null) { 16 | instance = new DaoFactory(); 17 | } 18 | return instance; 19 | } 20 | 21 | public DoctorDao getDoctorDao() throws SQLException{ 22 | return new DoctorDao(ConnectionManager.getConnection()); 23 | } 24 | 25 | public PatientDao getPatientDao() throws SQLException { 26 | return new PatientDao(ConnectionManager.getConnection()); 27 | } 28 | 29 | public PrescriptionDao getPrescriptionDao() throws SQLException { 30 | return new PrescriptionDao(ConnectionManager.getConnection()); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/dao/ConnectionManager.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.dao; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.SQLException; 6 | 7 | public class ConnectionManager { 8 | 9 | private static Connection connection = null; 10 | 11 | private ConnectionManager() { 12 | } 13 | 14 | public static Connection getConnection() throws SQLException { 15 | if (connection == null) { 16 | final String user = "SA"; 17 | final String password = ""; 18 | final String url = "jdbc:hsqldb:file:db"; 19 | final String driver = "org.hsqldb.jdbc.JDBCDriver"; 20 | try { 21 | Class.forName(driver); 22 | } catch (Exception e) { 23 | throw new SQLException("Problems with getting a connection to the database object!"); 24 | } 25 | connection = DriverManager.getConnection(url, user, password); 26 | } 27 | return connection; 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/hsqldb/dto/PersonFullName.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.hsqldb.dto; 2 | 3 | import com.zufar.testtask.model.Identified; 4 | 5 | public class PersonFullName implements Identified { 6 | 7 | private Long id; 8 | private String firstName; 9 | private String lastName; 10 | private String patronymic; 11 | 12 | public PersonFullName( 13 | Long id, 14 | String firstName, 15 | String lastName, 16 | String patronymic 17 | ) { 18 | this.id = id; 19 | this.firstName = firstName; 20 | this.lastName = lastName; 21 | this.patronymic = patronymic; 22 | } 23 | 24 | public String getPatronymic() { 25 | return patronymic; 26 | } 27 | 28 | public void setPatronymic( String patronymic) { 29 | this.patronymic = patronymic; 30 | } 31 | 32 | @Override 33 | public Long getId() { 34 | return id; 35 | } 36 | 37 | @Override 38 | public void setId(Long id) { 39 | this.id = id; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return lastName + " " + firstName + " " + patronymic; 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | Vaadin Web Application 7 | 8 | Vaadin production mode 9 | productionMode 10 | false 11 | 12 | 13 | Vaadin Application Servlet 14 | com.vaadin.server.VaadinServlet 15 | 16 | Vaadin UI to display 17 | UI 18 | com.zufar.testtask.ui.MainUI 19 | 20 | 21 | 22 | Vaadin Application Servlet 23 | /* 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/MainUI.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui; 2 | 3 | import com.zufar.testtask.ui.layout.DoctorVerticalLayout; 4 | import com.zufar.testtask.ui.layout.PatientVerticalLayout; 5 | import com.zufar.testtask.ui.layout.PrescriptionVerticalLayout; 6 | import com.vaadin.annotations.Theme; 7 | import com.vaadin.annotations.Title; 8 | import com.vaadin.server.VaadinRequest; 9 | import com.vaadin.ui.themes.ValoTheme; 10 | import com.vaadin.ui.*; 11 | 12 | @Title("Hospital") 13 | @Theme(ValoTheme.THEME_NAME) 14 | public class MainUI extends UI { 15 | 16 | private DoctorVerticalLayout dctorVerticalLayout = new DoctorVerticalLayout(); 17 | private PatientVerticalLayout patientVerticalLayout = new PatientVerticalLayout(); 18 | private PrescriptionVerticalLayout prescriptionVerticalLayout = new PrescriptionVerticalLayout(); 19 | 20 | @Override 21 | protected void init(VaadinRequest request) { 22 | VerticalLayout rootVerticalLayout = new VerticalLayout( 23 | dctorVerticalLayout, 24 | patientVerticalLayout, 25 | prescriptionVerticalLayout 26 | ); 27 | setContent(rootVerticalLayout); 28 | rootVerticalLayout.setMargin(true); 29 | } 30 | 31 | public PrescriptionVerticalLayout getPrescriptionVerticalLayout() { 32 | return prescriptionVerticalLayout; 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/window/AbstractWindow.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.window; 2 | 3 | import com.zufar.testtask.ui.MainUI; 4 | import com.vaadin.server.FontAwesome; 5 | import com.vaadin.ui.*; 6 | 7 | abstract class AbstractWindow extends Window { 8 | 9 | Button cancelButton = new Button("Cancel", event -> close()); 10 | Button okButton = new Button("Ok", this::actionAfterClickOkButton); 11 | VerticalLayout verticalFields = new VerticalLayout(); 12 | 13 | AbstractWindow() { 14 | commonActions(); 15 | } 16 | 17 | abstract void actionAfterClickOkButton(Button.ClickEvent clickEvent); 18 | 19 | private void commonActions() { 20 | verticalFields.setSpacing(true); 21 | verticalFields.setMargin(true); 22 | center(); 23 | setModal(true); 24 | setSizeUndefined(); 25 | HorizontalLayout buttonsLayout = new HorizontalLayout(okButton, cancelButton); 26 | buttonsLayout.setSpacing(true); 27 | VerticalLayout verticalMain = new VerticalLayout(verticalFields, buttonsLayout); 28 | verticalMain.setMargin(true); 29 | verticalMain.setComponentAlignment(buttonsLayout, Alignment.MIDDLE_CENTER); 30 | setContent(verticalMain); 31 | 32 | okButton.setEnabled(false); 33 | cancelButton.setEnabled(true); 34 | 35 | cancelButton.setIcon(FontAwesome.CLOSE); 36 | okButton.setIcon(FontAwesome.CHECK); 37 | 38 | okButton.setWidth(String.valueOf(120)); 39 | cancelButton.setWidth(String.valueOf(120)); 40 | } 41 | 42 | @Override 43 | public MainUI getUI() { 44 | return (MainUI) super.getUI(); 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/layout/AbstractVerticalLayout.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.layout; 2 | 3 | import com.zufar.testtask.ui.MainUI; 4 | import com.vaadin.server.FontAwesome; 5 | import com.vaadin.ui.*; 6 | 7 | abstract class AbstractVerticalLayout extends VerticalLayout { 8 | 9 | Grid grid = new Grid(); 10 | Label label = new Label(); 11 | Button addButton = new Button(); 12 | Button editButton = new Button(); 13 | Button deleteButton = new Button("Delete", this::actionAfterClickDeleteButton); 14 | HorizontalLayout buttonsLayout = new HorizontalLayout(); 15 | 16 | AbstractVerticalLayout() { 17 | configureCommonComponents(); 18 | } 19 | 20 | abstract void actionAfterClickDeleteButton(Button.ClickEvent event); 21 | 22 | private void configureCommonComponents() { 23 | addComponents(label, grid, buttonsLayout); 24 | buttonsLayout.addComponents(addButton, editButton, deleteButton); 25 | buttonsLayout.setSpacing(true); 26 | buttonsLayout.setMargin(true); 27 | addButton.setCaption("Add"); 28 | editButton.setCaption("Edit"); 29 | addButton.setEnabled(true); 30 | grid.setSizeFull(); 31 | grid.setSelectionMode(Grid.SelectionMode.SINGLE); 32 | configureComponentsWidth(); 33 | configureComponentsIcons(); 34 | } 35 | 36 | private void configureComponentsWidth() { 37 | addButton.setWidth("150"); 38 | editButton.setWidth("150"); 39 | deleteButton.setWidth("150"); 40 | } 41 | 42 | private void configureComponentsIcons() { 43 | addButton.setIcon(FontAwesome.PLUS); 44 | editButton.setIcon(FontAwesome.EDIT); 45 | deleteButton.setIcon(FontAwesome.TRASH); 46 | } 47 | 48 | @Override 49 | public MainUI getUI() { 50 | return (MainUI) super.getUI(); 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/model/Doctor.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.model; 2 | 3 | public class Doctor implements Identified { 4 | 5 | private Long id; 6 | private String firstName; 7 | private String lastName; 8 | private String patronymic; 9 | private String specialization; 10 | 11 | public Doctor( 12 | String firstName, 13 | String lastName, 14 | String patronymic, 15 | String specialization 16 | ) { 17 | this.firstName = firstName; 18 | this.lastName = lastName; 19 | this.patronymic = patronymic; 20 | this.specialization = specialization; 21 | } 22 | 23 | public Doctor() { 24 | } 25 | 26 | public String getFirstName() { 27 | return firstName; 28 | } 29 | 30 | public void setFirstName(String firstName) { 31 | this.firstName = firstName; 32 | } 33 | 34 | public String getLastName() { 35 | return lastName; 36 | } 37 | 38 | public void setLastName(String lastName) { 39 | this.lastName = lastName; 40 | } 41 | 42 | public String getPatronymic() { 43 | return patronymic; 44 | } 45 | 46 | public void setPatronymic(String patronymic) { 47 | this.patronymic = patronymic; 48 | } 49 | 50 | public String getSpecialization() { 51 | return specialization; 52 | } 53 | 54 | public void setSpecialization(String specialization) { 55 | this.specialization = specialization; 56 | } 57 | 58 | @Override 59 | public Long getId() { 60 | return id; 61 | } 62 | 63 | @Override 64 | public void setId(Long primaryKey) { 65 | this.id = primaryKey; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return this.firstName + " " + this.lastName + " " + this.patronymic + " " + this.specialization; 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/model/Patient.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.model; 2 | 3 | public class Patient implements Identified { 4 | 5 | private Long id; 6 | private String firstName; 7 | private String lastName; 8 | private String patronymic; 9 | private Long telephoneNumber; 10 | 11 | public Patient() { 12 | } 13 | 14 | public Patient( 15 | String firstName, 16 | String lastName, 17 | String patronymic, 18 | Long telephoneNumber 19 | ) { 20 | this.firstName = firstName; 21 | this.lastName = lastName; 22 | this.patronymic = patronymic; 23 | this.telephoneNumber = telephoneNumber; 24 | } 25 | 26 | public String getFirstName() { 27 | return firstName; 28 | } 29 | 30 | public void setFirstName(String firstName) { 31 | this.firstName = firstName; 32 | } 33 | 34 | public String getLastName() { 35 | return lastName; 36 | } 37 | 38 | public void setLastName(String lastName) { 39 | this.lastName = lastName; 40 | } 41 | 42 | public String getPatronymic() { 43 | return patronymic; 44 | } 45 | 46 | public void setPatronymic(String patronymic) { 47 | this.patronymic = patronymic; 48 | } 49 | 50 | public Long getTelephoneNumber() { 51 | return telephoneNumber; 52 | } 53 | 54 | public void setTelephoneNumber(Long telephoneNumber) { 55 | this.telephoneNumber = telephoneNumber; 56 | } 57 | 58 | @Override 59 | public Long getId() { 60 | return id; 61 | } 62 | 63 | @Override 64 | public void setId(Long primaryKey) { 65 | this.id = primaryKey; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return this.firstName + " " + this.lastName + " " + this.patronymic + " " + this.telephoneNumber; 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/model/Prescription.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.model; 2 | 3 | import com.zufar.testtask.hsqldb.dto.PersonFullName; 4 | 5 | import java.time.LocalDate; 6 | 7 | public class Prescription implements Identified { 8 | 9 | private Long id; 10 | private String description; 11 | private PersonFullName patient; 12 | private PersonFullName doctor; 13 | private LocalDate creationDate; 14 | private Long validity; 15 | private Priority priority; 16 | 17 | public Prescription( 18 | Long id, 19 | String description, 20 | PersonFullName patientFullName, 21 | PersonFullName doctorFullName, 22 | LocalDate creationDate, 23 | Long validity, 24 | Priority priority 25 | ) { 26 | this.id = id; 27 | this.description = description; 28 | this.patient = patientFullName; 29 | this.doctor = doctorFullName; 30 | this.creationDate = creationDate; 31 | this.validity = validity; 32 | this.priority = priority; 33 | } 34 | 35 | public Prescription( 36 | String description, 37 | PersonFullName patientFullName, 38 | PersonFullName doctorFullName, 39 | LocalDate creationDate, 40 | Long validity, 41 | Priority priority 42 | ) { 43 | this.description = description; 44 | this.patient = patientFullName; 45 | this.doctor = doctorFullName; 46 | this.creationDate = creationDate; 47 | this.validity = validity; 48 | this.priority = priority; 49 | } 50 | 51 | public String getDescription() { 52 | return description; 53 | } 54 | 55 | public PersonFullName getPatient() { 56 | return patient; 57 | } 58 | 59 | public PersonFullName getDoctor() { 60 | return doctor; 61 | } 62 | 63 | public LocalDate getCreationDate() { 64 | return creationDate; 65 | } 66 | 67 | public Long getValidity() { 68 | return validity; 69 | } 70 | 71 | public Priority getPriority() { 72 | return priority; 73 | } 74 | 75 | @Override 76 | public Long getId() { 77 | return id; 78 | } 79 | 80 | @Override 81 | public void setId(Long id) { 82 | this.id = id; 83 | } 84 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/layout/PatientVerticalLayout.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.layout; 2 | 3 | import com.zufar.testtask.hsqldb.DaoFactory; 4 | import com.zufar.testtask.model.Patient; 5 | import com.zufar.testtask.ui.window.PatientWindow; 6 | import com.vaadin.data.util.BeanItemContainer; 7 | import com.vaadin.ui.*; 8 | 9 | import java.sql.SQLException; 10 | import java.util.List; 11 | 12 | public class PatientVerticalLayout extends AbstractVerticalLayout { 13 | 14 | public PatientVerticalLayout() { 15 | configureComponents(); 16 | } 17 | 18 | private void configureComponents() { 19 | addButton.addClickListener(clickEvent -> UI.getCurrent().addWindow(new PatientWindow(this, null))); 20 | editButton.addClickListener(clickEvent -> { 21 | if (grid.getSelectedRow() == null) { 22 | disableButtons(); 23 | } else { 24 | UI.getCurrent().addWindow(new PatientWindow(this, (Patient) grid.getSelectedRow())); 25 | } 26 | }); 27 | label.setValue("Patient's list"); 28 | disableButtons(); 29 | configureGrid(); 30 | refreshGrid(); 31 | } 32 | 33 | private void configureGrid() { 34 | grid.setContainerDataSource(new BeanItemContainer<>(Patient.class)); 35 | grid.setColumnOrder("lastName", "firstName", "patronymic", "telephoneNumber"); 36 | grid.removeColumn("id"); 37 | grid.addSelectionListener(selectionEvent -> { 38 | editButton.setEnabled(true); 39 | deleteButton.setEnabled(true); 40 | }); 41 | } 42 | 43 | public void refreshGrid() { 44 | try { 45 | List patients = DaoFactory.getInstance().getPatientDao().getAll(); 46 | grid.setContainerDataSource(new BeanItemContainer<>(Patient.class, patients)); 47 | } catch (SQLException e) { 48 | Notification.show("Deleting this doctor is impossible!", "There are some problems with the database.", 49 | Notification.Type.ERROR_MESSAGE); 50 | } 51 | } 52 | 53 | void actionAfterClickDeleteButton(Button.ClickEvent event) { 54 | disableButtons(); 55 | Patient selectedRow = (Patient) grid.getSelectedRow(); 56 | if (selectedRow == null) { 57 | return; 58 | } 59 | try { 60 | DaoFactory.getInstance().getPatientDao().delete(selectedRow); 61 | getUI().getPrescriptionVerticalLayout().refreshGrid(null); 62 | getUI().getPrescriptionVerticalLayout().refreshPatientFilter(); 63 | refreshGrid(); 64 | } catch (java.sql.SQLIntegrityConstraintViolationException e) { 65 | Notification.show("Deleting this patient is impossible!", "There are some prescriptions which are connected with this patient.", 66 | Notification.Type.WARNING_MESSAGE); 67 | deleteButton.setEnabled(true); 68 | editButton.setEnabled(true); 69 | } catch (SQLException e) { 70 | Notification.show("Deleting this patient is impossible!", "There are some problems with the database.", 71 | Notification.Type.ERROR_MESSAGE); 72 | } 73 | } 74 | 75 | public void disableButtons() { 76 | deleteButton.setEnabled(false); 77 | editButton.setEnabled(false); 78 | } 79 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/dao/AbstractCrudDao.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.dao; 2 | 3 | import com.zufar.testtask.model.Identified; 4 | 5 | import java.sql.Connection; 6 | import java.sql.PreparedStatement; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | import java.util.List; 10 | 11 | public abstract class AbstractCrudDao, Id extends Long> implements CrudDao { 12 | 13 | protected Connection connection; 14 | 15 | /* Возвращает sql запрос для вставки новой записи в БД */ 16 | protected abstract String getCreateQuery(); 17 | 18 | /* Возвращает sql запрос для получения всех записей из БД */ 19 | protected abstract String getSelectQuery(); 20 | 21 | /* Возвращает sql запрос для обновления записи в БД */ 22 | protected abstract String getUpdateQuery(); 23 | 24 | /* Возвращает sql запрос для удаления записи из БД */ 25 | protected abstract String getDeleteQuery(); 26 | 27 | public AbstractCrudDao(Connection connection) { 28 | this.connection = connection; 29 | } 30 | 31 | /* Возвращает список объектов соответствующих содержимому ResultSet */ 32 | protected abstract List parseResultSet(ResultSet resultSet) throws SQLException; 33 | 34 | /* Устанавливает аргументы в запрос insert в соответствии со значением полей объекта object */ 35 | protected abstract void prepareStatementForInsert(PreparedStatement preparedStatement, E object) throws SQLException; 36 | 37 | /* Устанавливает аргументы в запрос update в соответствии со значением полей объекта object */ 38 | protected abstract void prepareStatementForUpdate(PreparedStatement preparedStatement, E object) throws SQLException; 39 | 40 | @Override 41 | public void create(E object) throws SQLException { 42 | String createQuery = getCreateQuery(); 43 | PreparedStatement statement = connection.prepareStatement(createQuery); 44 | prepareStatementForInsert(statement, object); 45 | statement.executeUpdate(); 46 | } 47 | 48 | @Override 49 | public E get(Long id) throws SQLException { 50 | String selectQuery = String.format("%s WHERE id = ?", getSelectQuery()); 51 | PreparedStatement statement = connection.prepareStatement(selectQuery); 52 | statement.setLong(1, id); 53 | ResultSet resultSet = statement.executeQuery(); 54 | List objects = parseResultSet(resultSet); 55 | return objects.iterator().next(); 56 | } 57 | 58 | @Override 59 | public void update(E object) throws SQLException { 60 | String updateQuery = getUpdateQuery(); 61 | PreparedStatement preparedStatement = connection.prepareStatement(updateQuery); 62 | prepareStatementForUpdate(preparedStatement, object); 63 | preparedStatement.executeUpdate(); 64 | } 65 | 66 | @Override 67 | public void delete(E object) throws SQLException { 68 | String deleteQuery = getDeleteQuery(); 69 | PreparedStatement preparedStatement = connection.prepareStatement(deleteQuery); 70 | preparedStatement.setObject(1, object.getId()); 71 | preparedStatement.executeUpdate(); 72 | } 73 | 74 | @Override 75 | public List getAll() throws SQLException { 76 | String selectQuery = getSelectQuery(); 77 | PreparedStatement preparedStatement = connection.prepareStatement(selectQuery); 78 | ResultSet resultSet = preparedStatement.executeQuery(); 79 | return parseResultSet(resultSet); 80 | } 81 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/hsqldb/PatientDao.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.hsqldb; 2 | 3 | import com.zufar.testtask.dao.AbstractCrudDao; 4 | import com.zufar.testtask.hsqldb.dto.PersonFullName; 5 | import com.zufar.testtask.model.Patient; 6 | 7 | import java.sql.Connection; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class PatientDao extends AbstractCrudDao { 15 | 16 | PatientDao(Connection connection) { 17 | super(connection); 18 | } 19 | 20 | @Override 21 | public String getSelectQuery() { 22 | return "SELECT id, first_name, last_name, patronymic, telephone_number FROM PATIENT"; 23 | } 24 | 25 | @Override 26 | public String getCreateQuery() { 27 | return "INSERT INTO PATIENT (first_name, last_name, patronymic, telephone_number) VALUES (?, ?, ?, ?)"; 28 | } 29 | 30 | @Override 31 | public String getUpdateQuery() { 32 | return "UPDATE PATIENT SET first_name = ?, last_name = ?, patronymic = ?, telephone_number = ? WHERE id = ?"; 33 | } 34 | 35 | @Override 36 | public String getDeleteQuery() { 37 | return "DELETE FROM PATIENT WHERE id = ?"; 38 | } 39 | 40 | @Override 41 | protected List parseResultSet(ResultSet resultSet) throws SQLException { 42 | List patients = new ArrayList<>(); 43 | while (resultSet.next()) { 44 | Patient patient = new Patient(); 45 | patient.setId(resultSet.getLong("id")); 46 | patient.setFirstName((resultSet.getString("first_name"))); 47 | patient.setLastName(resultSet.getString("last_name")); 48 | patient.setPatronymic(resultSet.getString("patronymic")); 49 | patient.setTelephoneNumber(resultSet.getLong("telephone_number")); 50 | patients.add(patient); 51 | } 52 | return patients; 53 | } 54 | 55 | @Override 56 | protected void prepareStatementForUpdate(PreparedStatement preparedStatement, Patient patient) 57 | throws SQLException, IllegalArgumentException { 58 | if (patient.getFirstName() == null || patient.getLastName() == null || patient.getPatronymic() == null || 59 | patient.getTelephoneNumber() == null || patient.getId() == null) { 60 | throw new IllegalArgumentException("Some patient object's fields are absent!"); 61 | } 62 | preparedStatement.setString(1, patient.getFirstName()); 63 | preparedStatement.setString(2, patient.getLastName()); 64 | preparedStatement.setString(3, patient.getPatronymic()); 65 | preparedStatement.setLong(4, patient.getTelephoneNumber()); 66 | preparedStatement.setLong(5, patient.getId()); 67 | } 68 | 69 | @Override 70 | protected void prepareStatementForInsert(PreparedStatement preparedStatement, Patient patient) 71 | throws SQLException, IllegalArgumentException { 72 | if (patient.getFirstName() == null || patient.getLastName() == null || patient.getPatronymic() == null || 73 | patient.getTelephoneNumber() == null) { 74 | throw new IllegalArgumentException("Some patient object's fields are absent!"); 75 | } 76 | preparedStatement.setString(1, patient.getFirstName()); 77 | preparedStatement.setString(2, patient.getLastName()); 78 | preparedStatement.setString(3, patient.getPatronymic()); 79 | preparedStatement.setLong(4, patient.getTelephoneNumber()); 80 | } 81 | 82 | 83 | public List getAllFullNames() throws SQLException { 84 | PreparedStatement preparedStatement = connection.prepareStatement("SELECT id, first_name, last_name, patronymic FROM PATIENT"); 85 | ResultSet resultSet = preparedStatement.executeQuery(); 86 | List patientsFullNames = new ArrayList<>(); 87 | while (resultSet.next()) { 88 | patientsFullNames.add(new PersonFullName( 89 | resultSet.getLong("id"), 90 | resultSet.getString("first_name"), 91 | resultSet.getString("last_name"), 92 | resultSet.getString("patronymic") 93 | )); 94 | } 95 | return patientsFullNames; 96 | } 97 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/layout/DoctorVerticalLayout.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.layout; 2 | 3 | import com.zufar.testtask.hsqldb.DaoFactory; 4 | import com.zufar.testtask.model.Doctor; 5 | import com.zufar.testtask.ui.window.DoctorWindow; 6 | import com.vaadin.data.util.BeanItemContainer; 7 | import com.vaadin.server.FontAwesome; 8 | import com.vaadin.ui.*; 9 | 10 | import java.sql.SQLException; 11 | import java.util.List; 12 | 13 | public class DoctorVerticalLayout extends AbstractVerticalLayout { 14 | 15 | private Button statisticsButton = new Button("Statistics", this::actionAfterClickStatisticsButton); 16 | 17 | public DoctorVerticalLayout() { 18 | configureComponents(); 19 | } 20 | 21 | private void configureComponents() { 22 | buttonsLayout.addComponents(statisticsButton); 23 | label.setValue("Doctor's list"); 24 | statisticsButton.setIcon(FontAwesome.BAR_CHART); 25 | statisticsButton.setWidth("150"); 26 | configureComponentsActionListeners(); 27 | disableButtons(); 28 | configureGrid(); 29 | refreshGrid(); 30 | } 31 | 32 | private void configureComponentsActionListeners() { 33 | addButton.addClickListener(clickEvent -> UI.getCurrent().addWindow(new DoctorWindow(this, null))); 34 | editButton.addClickListener(clickEvent -> { 35 | if (grid.getSelectedRow() == null) { 36 | disableButtons(); 37 | } else { 38 | UI.getCurrent().addWindow(new DoctorWindow(this, (Doctor) grid.getSelectedRow())); 39 | } 40 | }); 41 | } 42 | 43 | private void configureGrid() { 44 | grid.setContainerDataSource(new BeanItemContainer<>(Doctor.class)); 45 | grid.setColumnOrder("lastName", "firstName", "patronymic", "specialization"); 46 | grid.removeColumn("id"); 47 | grid.addSelectionListener(selectionEvent -> { 48 | deleteButton.setEnabled(true); 49 | editButton.setEnabled(true); 50 | statisticsButton.setEnabled(true); 51 | }); 52 | } 53 | 54 | public void refreshGrid() { 55 | try { 56 | List doctors = DaoFactory.getInstance().getDoctorDao().getAll(); 57 | grid.setContainerDataSource(new BeanItemContainer<>(Doctor.class, doctors)); 58 | } catch (SQLException e) { 59 | Notification.show("Deleting this doctor is impossible!", "There are some problems with the database.", 60 | Notification.Type.ERROR_MESSAGE); 61 | } 62 | } 63 | 64 | void actionAfterClickDeleteButton(Button.ClickEvent event) { 65 | disableButtons(); 66 | Doctor selectedRow = (Doctor) grid.getSelectedRow(); 67 | if (selectedRow == null) { 68 | return; 69 | } 70 | try { 71 | DaoFactory.getInstance().getDoctorDao().delete(selectedRow); 72 | getUI().getPrescriptionVerticalLayout().refreshGrid(null); 73 | refreshGrid(); 74 | } catch (java.sql.SQLIntegrityConstraintViolationException e) { 75 | Notification.show("Deleting this doctor is impossible!", "There are some prescriptions which are connected with this doctor.", 76 | Notification.Type.WARNING_MESSAGE); 77 | deleteButton.setEnabled(true); 78 | editButton.setEnabled(true); 79 | statisticsButton.setEnabled(true); 80 | } catch (SQLException e) { 81 | Notification.show("Deleting this doctor is impossible!", "There are some problems with the database.", 82 | Notification.Type.ERROR_MESSAGE); 83 | } 84 | } 85 | 86 | private void actionAfterClickStatisticsButton(Button.ClickEvent event) { 87 | Doctor selectedRow = (Doctor) grid.getSelectedRow(); 88 | if (selectedRow == null || selectedRow.getId() == null) { 89 | disableButtons(); 90 | return; 91 | } 92 | try { 93 | Long statistics = DaoFactory.getInstance().getDoctorDao().getStatistics(selectedRow.getId()); 94 | Notification.show("Note!", "This doctor made " + statistics + " prescription(s).", 95 | Notification.Type.WARNING_MESSAGE); 96 | } catch (SQLException e) { 97 | Notification.show("Deleting this doctor is impossible!", "There are some problems with the database.", 98 | Notification.Type.ERROR_MESSAGE); 99 | } 100 | } 101 | 102 | public void disableButtons() { 103 | deleteButton.setEnabled(false); 104 | editButton.setEnabled(false); 105 | statisticsButton.setEnabled(false); 106 | } 107 | } -------------------------------------------------------------------------------- /db.script: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA PUBLIC AUTHORIZATION DBA 2 | SET DATABASE DEFAULT INITIAL SCHEMA PUBLIC 3 | CREATE USER SA PASSWORD "" 4 | GRANT DBA TO SA 5 | SET SCHEMA PUBLIC 6 | CREATE MEMORY TABLE PATIENT(id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) PRIMARY KEY, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, patronymic VARCHAR(50) NOT NULL,telephone_number BIGINT NOT NULL); 7 | CREATE MEMORY TABLE DOCTOR(id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) PRIMARY KEY, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, patronymic VARCHAR(50) NOT NULL, specialization VARCHAR(50) NOT NULL); 8 | CREATE MEMORY TABLE PRESCRIPTION(id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1) PRIMARY KEY, description VARCHAR(200) NOT NULL, patient_id BIGINT NOT NULL, doctor_id BIGINT NOT NULL, creation_date DATE NOT NULL, validity BIGINT NOT NULL, priority VARCHAR(10) NOT NULL, FOREIGN KEY (patient_id) REFERENCES PATIENT(id) ON DELETE NO ACTION, FOREIGN KEY (doctor_id) REFERENCES DOCTOR(id) ON DELETE NO ACTION); 9 | SET SCHEMA PUBLIC; 10 | SET WRITE_DELAY 10; 11 | INSERT INTO PATIENT VALUES(1,'Anastasia','Vasileva','Aleksandrovna',252525); 12 | INSERT INTO PATIENT VALUES(2,'Boris','Babushkin','Georgiyevich', 242422); 13 | INSERT INTO PATIENT VALUES(3,'Viktor','Georgiyev','Iosifovich',4636456); 14 | INSERT INTO PATIENT VALUES(4,'Dmitry','Dudinsky','Innokentyevich',5464564); 15 | INSERT INTO PATIENT VALUES(5,'Yelena','Yeremeyeva','Karpovna',5464564); 16 | INSERT INTO PATIENT VALUES(6,'Pyotr','Vorobyov','Lvovich',5464564); 17 | INSERT INTO PATIENT VALUES(7,'Ella','Runieva','Aleksandrova',252525); 18 | INSERT INTO PATIENT VALUES(8,'Boris','Malyshev','Nikolayevich', 242422); 19 | INSERT INTO PATIENT VALUES(9,'Viktor','Smelyansky','Maratovich',4636456); 20 | INSERT INTO PATIENT VALUES(10,'Dmitry','Tatishchev','Olegovich',5464564); 21 | INSERT INTO PATIENT VALUES(11,'Yelena','Frolova','Kirillovna',5464564); 22 | INSERT INTO PATIENT VALUES(12,'Pyotr','Tikhonov','Lvovich',5464564); 23 | INSERT INTO DOCTOR VALUES (1,'Zhanna','Strizheva','Maratovna','Surgeon'); 24 | INSERT INTO DOCTOR VALUES (2,'Zoya','Udalova','Maksimovna', 'Dentist'); 25 | INSERT INTO DOCTOR VALUES (3,'Irina','Vafina','Kirillovna','Therapist'); 26 | INSERT INTO DOCTOR VALUES (4,'Andrey','Malyshev','Ilyich','Dentist'); 27 | INSERT INTO DOCTOR VALUES (5,'Ksenia','Akopyan','Leontyevna','Neurologist'); 28 | INSERT INTO DOCTOR VALUES (6,'Leonid','Kovalsky','Glebovich','Therapist'); 29 | INSERT INTO DOCTOR VALUES (7,'Leonid ','Vorobyov','Ibragimovich','Neurologist'); 30 | INSERT INTO DOCTOR VALUES (8,'Maria','Lushina','Karpovna', 'Dentist'); 31 | INSERT INTO DOCTOR VALUES (9,'Ruslan','Nuriyev','Antonovich','Therapist'); 32 | INSERT INTO DOCTOR VALUES (10,'Pavel','Lapshin','Georgiyevich','Dermatologist'); 33 | INSERT INTO DOCTOR VALUES (11,'Oleg','Stroyev','Losifovich','Dermatologist'); 34 | INSERT INTO DOCTOR VALUES (12,'Natalia','Anichkina','Innokentyevna','Therapist'); 35 | INSERT INTO PRESCRIPTION VALUES (1,'You should more sleep.',8,1,'2012-08-07', 100,'STATIM'); 36 | INSERT INTO PRESCRIPTION VALUES (2,'You should more relax.',9,1,'2001-07-10',150,'NORMAL'); 37 | INSERT INTO PRESCRIPTION VALUES (3,'You should more run.',3,1,'2008-08-01',300,'SITO'); 38 | INSERT INTO PRESCRIPTION VALUES (4,'You should more smile.',4,1,'2015-08-07',500, 'STATIM'); 39 | INSERT INTO PRESCRIPTION VALUES (5,'You should more relax.',5,2,'2012-08-07', 100,'NORMAL'); 40 | INSERT INTO PRESCRIPTION VALUES (6,'You should more eat.',6,2,'2001-07-10',150,'NORMAL'); 41 | INSERT INTO PRESCRIPTION VALUES (7,'You should more run.',7,2,'2008-08-01',300,'SITO'); 42 | INSERT INTO PRESCRIPTION VALUES (8,'You should more sleep.',8,3,'2015-08-07',500, 'NORMAL'); 43 | INSERT INTO PRESCRIPTION VALUES (9,'You should more smile.',9,4,'2012-08-07', 100,'NORMAL'); 44 | INSERT INTO PRESCRIPTION VALUES (10,'You should more drink.',10,4,'2001-07-10',150,'STATIM'); 45 | INSERT INTO PRESCRIPTION VALUES (11,'You should more eat.',11,5,'2008-08-01',300,'NORMAL'); 46 | INSERT INTO PRESCRIPTION VALUES (12,'You should more sleep.',12,6,'2015-08-07',500, 'SITO'); 47 | INSERT INTO PRESCRIPTION VALUES (13,'You should more drink.',1,7,'2012-08-07', 100,'NORMAL'); 48 | INSERT INTO PRESCRIPTION VALUES (14,'You should more run.',2,7,'2001-07-10',150,'NORMAL'); 49 | INSERT INTO PRESCRIPTION VALUES (15,'You should more relax.',7,7,'2008-08-01',300,'STATIM'); 50 | INSERT INTO PRESCRIPTION VALUES (16,'You should more sleep.',5,8,'2015-08-07',500, 'NORMAL'); 51 | INSERT INTO PRESCRIPTION VALUES (17,'You should more relax.',6,8,'2012-08-07', 100,'SITO'); 52 | INSERT INTO PRESCRIPTION VALUES (18,'You should more sleep.',2,1,'2001-07-10',150,'STATIM'); 53 | INSERT INTO PRESCRIPTION VALUES (19,'You should more smile.',3,4,'2008-08-01',300,'NORMAL'); 54 | INSERT INTO PRESCRIPTION VALUES (20,'You should more run.',4,3,'2015-08-07',500, 'NORMAL'); -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/hsqldb/DoctorDao.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.hsqldb; 2 | 3 | import com.zufar.testtask.dao.AbstractCrudDao; 4 | import com.zufar.testtask.hsqldb.dto.PersonFullName; 5 | import com.zufar.testtask.model.Doctor; 6 | 7 | import java.sql.Connection; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class DoctorDao extends AbstractCrudDao { 15 | 16 | DoctorDao(Connection connection) { 17 | super(connection); 18 | } 19 | 20 | @Override 21 | public String getSelectQuery() { 22 | return "SELECT id, first_name, last_name, patronymic, specialization FROM DOCTOR"; 23 | } 24 | 25 | @Override 26 | public String getCreateQuery() { 27 | return "INSERT INTO DOCTOR (first_name, last_name, patronymic, specialization) VALUES (?, ?, ?, ?)"; 28 | } 29 | 30 | @Override 31 | public String getUpdateQuery() { 32 | return "UPDATE DOCTOR SET first_name = ?, last_name = ?, patronymic = ?, specialization = ? WHERE id = ?"; 33 | } 34 | 35 | @Override 36 | public String getDeleteQuery() { 37 | return "DELETE FROM DOCTOR WHERE id= ?"; 38 | } 39 | 40 | @Override 41 | protected List parseResultSet(ResultSet resultSet) throws SQLException { 42 | List doctors = new ArrayList<>(); 43 | while (resultSet.next()) { 44 | Doctor doctor = new Doctor(); 45 | doctor.setId(resultSet.getLong("id")); 46 | doctor.setFirstName((resultSet.getString("first_name"))); 47 | doctor.setLastName(resultSet.getString("last_name")); 48 | doctor.setPatronymic(resultSet.getString("patronymic")); 49 | doctor.setSpecialization(resultSet.getString("specialization")); 50 | doctors.add(doctor); 51 | } 52 | return doctors; 53 | } 54 | 55 | @Override 56 | protected void prepareStatementForUpdate(PreparedStatement preparedStatement, Doctor doctor) 57 | throws SQLException, IllegalArgumentException { 58 | if (doctor.getFirstName() == null || doctor.getLastName() == null || doctor.getPatronymic() == null || 59 | doctor.getSpecialization() == null || doctor.getId() == null) { 60 | throw new IllegalArgumentException("Some doctor object's fields are absent!"); 61 | } 62 | preparedStatement.setString(1, doctor.getFirstName()); 63 | preparedStatement.setString(2, doctor.getLastName()); 64 | preparedStatement.setString(3, doctor.getPatronymic()); 65 | preparedStatement.setString(4, doctor.getSpecialization()); 66 | preparedStatement.setLong(5, doctor.getId()); 67 | } 68 | 69 | @Override 70 | protected void prepareStatementForInsert(PreparedStatement preparedStatement, Doctor doctor) 71 | throws SQLException, IllegalArgumentException { 72 | if (doctor.getFirstName() == null || doctor.getLastName() == null || doctor.getPatronymic() == null || 73 | doctor.getSpecialization() == null) { 74 | throw new IllegalArgumentException("Some doctor object's fields are absent!"); 75 | } 76 | preparedStatement.setString(1, doctor.getFirstName()); 77 | preparedStatement.setString(2, doctor.getLastName()); 78 | preparedStatement.setString(3, doctor.getPatronymic()); 79 | preparedStatement.setString(4, doctor.getSpecialization()); 80 | } 81 | 82 | public List getAllFullNames() throws SQLException { 83 | PreparedStatement preparedStatement = connection.prepareStatement("SELECT id, first_name, last_name, patronymic FROM DOCTOR"); 84 | ResultSet resultSet = preparedStatement.executeQuery(); 85 | List doctorsFullNames = new ArrayList<>(); 86 | while (resultSet.next()) { 87 | doctorsFullNames.add(new PersonFullName( 88 | resultSet.getLong("id"), 89 | resultSet.getString("first_name"), 90 | resultSet.getString("last_name"), 91 | resultSet.getString("patronymic") 92 | )); 93 | } 94 | return doctorsFullNames; 95 | } 96 | 97 | public Long getStatistics(Long primaryKey) throws SQLException { 98 | PreparedStatement preparedStatement = connection.prepareStatement( 99 | "SELECT COUNT(id) AS prescription_count FROM PRESCRIPTION WHERE doctor_id = ?"); 100 | preparedStatement.setLong(1, primaryKey); 101 | ResultSet resultSet = preparedStatement.executeQuery(); 102 | if (resultSet.next()) { 103 | return resultSet.getLong("prescription_count"); 104 | } 105 | throw new SQLException(); 106 | } 107 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.zufar 6 | Hospital-Prescription 7 | war 8 | 1.0 9 | Test Task 10 | 11 | 12 | 13 | Zufar Sunagatov 14 | zuf999@mail.com 15 | 16 | architect 17 | developer 18 | 19 | 20 | 21 | 22 | 23 | UTF-8 24 | 7.6.7 25 | 26 | 27 | 28 | 29 | vaadin-addons 30 | http://maven.vaadin.com/vaadin-addons 31 | 32 | 33 | vaadin-snapshots 34 | http://oss.sonatype.org/content/repositories/vaadin-snapshots/ 35 | 36 | false 37 | 38 | 39 | true 40 | 41 | 42 | 43 | 44 | 45 | vaadin-snapshots 46 | http://oss.sonatype.org/content/repositories/vaadin-snapshots/ 47 | 48 | false 49 | 50 | 51 | true 52 | 53 | 54 | 55 | 56 | 57 | com.vaadin 58 | vaadin-server 59 | ${vaadin.version} 60 | 61 | 62 | com.vaadin 63 | vaadin-client-compiled 64 | ${vaadin.version} 65 | 66 | 67 | com.vaadin 68 | vaadin-themes 69 | ${vaadin.version} 70 | 71 | 72 | javax.servlet 73 | servlet-api 74 | 2.4 75 | provided 76 | 77 | 78 | org.hsqldb 79 | hsqldb 80 | 2.3.4 81 | 82 | 83 | 84 | 85 | src/main/java 86 | src/test/java 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-compiler-plugin 91 | 3.5.1 92 | 93 | 1.8 94 | 1.8 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-dependency-plugin 100 | 101 | ${project.build.directory}/lib/ 102 | false 103 | false 104 | true 105 | 106 | junit 107 | 108 | 109 | 110 | copy-dependencies 111 | package 112 | 113 | copy-dependencies 114 | 115 | 116 | 117 | 118 | 119 | org.mortbay.jetty 120 | jetty-maven-plugin 121 | 8.1.16.v20140903 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/window/DoctorWindow.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.window; 2 | 3 | import com.zufar.testtask.ui.layout.DoctorVerticalLayout; 4 | import com.vaadin.data.validator.StringLengthValidator; 5 | import com.vaadin.data.validator.RegexpValidator; 6 | import com.zufar.testtask.hsqldb.DaoFactory; 7 | import com.zufar.testtask.hsqldb.DoctorDao; 8 | import com.zufar.testtask.model.Doctor; 9 | import com.vaadin.event.FieldEvents; 10 | import com.vaadin.data.Validator; 11 | 12 | import java.sql.SQLException; 13 | 14 | import com.vaadin.ui.*; 15 | 16 | public class DoctorWindow extends AbstractWindow { 17 | 18 | private TextField firstName = new TextField("First name:"); 19 | private TextField lastName = new TextField("Last name:"); 20 | private TextField patronymic = new TextField("Patronymic:"); 21 | private TextField specialization = new TextField("Specialization:"); 22 | private DoctorVerticalLayout doctorVerticalLayout; 23 | private Doctor selectedDoctor; 24 | 25 | public DoctorWindow(DoctorVerticalLayout doctorVerticalLayout, Doctor selectedDoctor) { 26 | this.doctorVerticalLayout = doctorVerticalLayout; 27 | this.selectedDoctor = selectedDoctor; 28 | this.verticalFields.addComponents(lastName, firstName, patronymic, specialization); 29 | configureComponents(); 30 | } 31 | 32 | private void configureComponents() { 33 | firstName.focus(); 34 | configureComponentsValidator(); 35 | configureComponentsWidth(); 36 | configureComponentsValidators(); 37 | configureComponentsValidationVisibility(); 38 | configureComponentsRequired(); 39 | configureComponentsTextChangeEventMode(); 40 | configureComponentsChangeListeners(); 41 | configureComponentsMaxLength(); 42 | configureComponentsImmediate(); 43 | configureComponentsValue(); 44 | } 45 | 46 | private void configureComponentsValidator() { 47 | RegexpValidator wordValidator = new RegexpValidator("[A-Z][a-z]{1,50}",true, 48 | "Enter the word length from 2 to 50 characters (with a capital letter)"); 49 | firstName.addValidator(wordValidator); 50 | lastName.addValidator(wordValidator); 51 | patronymic.addValidator(wordValidator); 52 | specialization.addValidator(wordValidator); 53 | } 54 | 55 | private void configureComponentsValue() { 56 | if (selectedDoctor == null) { 57 | return; 58 | } 59 | firstName.setValue(selectedDoctor.getFirstName()); 60 | lastName.setValue(selectedDoctor.getLastName()); 61 | patronymic.setValue(selectedDoctor.getPatronymic()); 62 | specialization.setValue(selectedDoctor.getSpecialization()); 63 | } 64 | 65 | private void configureComponentsImmediate() { 66 | firstName.setImmediate(true); 67 | lastName.setImmediate(true); 68 | patronymic.setImmediate(true); 69 | specialization.setImmediate(true); 70 | } 71 | 72 | private void configureComponentsChangeListeners() { 73 | firstName.addTextChangeListener(event -> actionAfterTextChangeEvent(event, firstName)); 74 | lastName.addTextChangeListener(event -> actionAfterTextChangeEvent(event, lastName)); 75 | patronymic.addTextChangeListener(event -> actionAfterTextChangeEvent(event, patronymic)); 76 | specialization.addTextChangeListener(event -> actionAfterTextChangeEvent(event, specialization)); 77 | } 78 | 79 | private void configureComponentsRequired() { 80 | firstName.setRequired(true); 81 | lastName.setRequired(true); 82 | patronymic.setRequired(true); 83 | specialization.setRequired(true); 84 | } 85 | 86 | private void configureComponentsTextChangeEventMode() { 87 | firstName.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 88 | lastName.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 89 | patronymic.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 90 | specialization.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 91 | } 92 | 93 | private void configureComponentsValidationVisibility() { 94 | firstName.setValidationVisible(true); 95 | lastName.setValidationVisible(true); 96 | patronymic.setValidationVisible(true); 97 | specialization.setValidationVisible(true); 98 | } 99 | 100 | private void configureComponentsValidators() { 101 | StringLengthValidator stringLengthValidator = 102 | new StringLengthValidator("Prompt is empty", 1, 50, false); 103 | firstName.addValidator(stringLengthValidator); 104 | lastName.addValidator(stringLengthValidator); 105 | patronymic.addValidator(stringLengthValidator); 106 | specialization.addValidator(stringLengthValidator); 107 | } 108 | 109 | private void configureComponentsMaxLength() { 110 | firstName.setMaxLength(50); 111 | lastName.setMaxLength(50); 112 | patronymic.setMaxLength(50); 113 | specialization.setMaxLength(50); 114 | } 115 | 116 | private void configureComponentsWidth() { 117 | firstName.setWidth(String.valueOf(300)); 118 | lastName.setWidth(String.valueOf(300)); 119 | patronymic.setWidth(String.valueOf(300)); 120 | specialization.setWidth(String.valueOf(300)); 121 | } 122 | 123 | void actionAfterClickOkButton(Button.ClickEvent clickEvent) { 124 | doctorVerticalLayout.disableButtons(); 125 | Doctor doctor = new Doctor(firstName.getValue(), lastName.getValue(), patronymic.getValue(), specialization.getValue()); 126 | try { 127 | DoctorDao doctorDao = DaoFactory.getInstance().getDoctorDao(); 128 | if (selectedDoctor == null) { 129 | doctorDao.create(doctor); 130 | } else { 131 | if (selectedDoctor.getId() == null) { 132 | throw new IllegalArgumentException(); 133 | } 134 | doctor.setId(selectedDoctor.getId()); 135 | doctorDao.update(doctor); 136 | } 137 | getUI().getPrescriptionVerticalLayout().refreshGrid(null); 138 | doctorVerticalLayout.refreshGrid(); 139 | close(); 140 | } catch (SQLException e) { 141 | Notification.show("Taking action for this doctor is impossible!", "There are some problems with the database.", 142 | Notification.Type.ERROR_MESSAGE); 143 | } 144 | } 145 | 146 | private void actionAfterTextChangeEvent(FieldEvents.TextChangeEvent event, TextField textField) { 147 | textField.setValue(event.getText()); 148 | textField.setCursorPosition(event.getCursorPosition()); 149 | try { 150 | firstName.validate(); 151 | lastName.validate(); 152 | patronymic.validate(); 153 | specialization.validate(); 154 | okButton.setEnabled(true); 155 | } catch (Validator.InvalidValueException e) { 156 | okButton.setEnabled(false); 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/window/PatientWindow.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.window; 2 | 3 | import com.zufar.testtask.hsqldb.PatientDao; 4 | import com.vaadin.data.validator.RegexpValidator; 5 | import com.zufar.testtask.hsqldb.DaoFactory; 6 | import com.zufar.testtask.model.Patient; 7 | import com.zufar.testtask.ui.layout.PatientVerticalLayout; 8 | import com.vaadin.data.Validator; 9 | import com.vaadin.data.util.converter.StringToLongConverter; 10 | import com.vaadin.data.validator.LongRangeValidator; 11 | import com.vaadin.data.validator.StringLengthValidator; 12 | import com.vaadin.event.FieldEvents; 13 | import com.vaadin.ui.*; 14 | 15 | import java.sql.SQLException; 16 | 17 | public class PatientWindow extends AbstractWindow { 18 | 19 | private TextField firstName = new TextField("First name:"); 20 | private TextField lastName = new TextField("Last name:"); 21 | private TextField patronymic = new TextField("Patronymic:"); 22 | private TextField telephoneNumber = new TextField("Telephone number:"); 23 | private PatientVerticalLayout patientVerticalLayout; 24 | private Patient selectedPatient; 25 | 26 | public PatientWindow(PatientVerticalLayout doctorVerticalLayout, Patient selectedPatient) { 27 | this.patientVerticalLayout = doctorVerticalLayout; 28 | this.selectedPatient = selectedPatient; 29 | this.verticalFields.addComponents(lastName, firstName, patronymic, telephoneNumber); 30 | configureComponents(); 31 | } 32 | 33 | private void configureComponents() { 34 | firstName.focus(); 35 | telephoneNumber.setConverter(new StringToLongConverter()); 36 | telephoneNumber.setNullRepresentation(""); 37 | configureComponentsValidator(); 38 | configureComponentsWidth(); 39 | configureComponentsValidators(); 40 | configureComponentsValidationVisibility(); 41 | configureComponentsRequired(); 42 | configureComponentsTextChangeEventMode(); 43 | configureComponentsChangeListeners(); 44 | configureComponentsMaxLength(); 45 | configureComponentsImmediate(); 46 | configureComponentsValue(); 47 | } 48 | 49 | private void configureComponentsValue() { 50 | if (selectedPatient == null) { 51 | return; 52 | } 53 | firstName.setValue(selectedPatient.getFirstName()); 54 | lastName.setValue(selectedPatient.getLastName()); 55 | patronymic.setValue(selectedPatient.getPatronymic()); 56 | telephoneNumber.setValue(String.valueOf(selectedPatient.getTelephoneNumber())); 57 | } 58 | 59 | private void configureComponentsValidator() { 60 | RegexpValidator wordValidator = new RegexpValidator("[A-Z][a-z]{1,50}", true, 61 | "Enter the word length from 3 to 50 characters (with a capital letter)"); 62 | firstName.addValidator(wordValidator); 63 | lastName.addValidator(wordValidator); 64 | patronymic.addValidator(wordValidator); 65 | telephoneNumber.addValidator(new LongRangeValidator("Value is negative", 0L, Long.MAX_VALUE)); 66 | } 67 | 68 | private void configureComponentsImmediate() { 69 | firstName.setImmediate(true); 70 | lastName.setImmediate(true); 71 | patronymic.setImmediate(true); 72 | telephoneNumber.setImmediate(true); 73 | } 74 | 75 | private void configureComponentsMaxLength() { 76 | firstName.setMaxLength(50); 77 | lastName.setMaxLength(50); 78 | patronymic.setMaxLength(50); 79 | telephoneNumber.setMaxLength(18); 80 | } 81 | 82 | private void configureComponentsChangeListeners() { 83 | firstName.addTextChangeListener(event -> actionAfterTextChangeEvent(event, firstName)); 84 | lastName.addTextChangeListener(event -> actionAfterTextChangeEvent(event, lastName)); 85 | patronymic.addTextChangeListener(event -> actionAfterTextChangeEvent(event, patronymic)); 86 | telephoneNumber.addTextChangeListener(event -> actionAfterTextChangeEvent(event, telephoneNumber)); 87 | } 88 | 89 | private void configureComponentsTextChangeEventMode() { 90 | firstName.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 91 | lastName.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 92 | patronymic.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 93 | telephoneNumber.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 94 | } 95 | 96 | private void configureComponentsRequired() { 97 | firstName.setRequired(true); 98 | lastName.setRequired(true); 99 | patronymic.setRequired(true); 100 | telephoneNumber.setRequired(true); 101 | } 102 | 103 | private void configureComponentsValidationVisibility() { 104 | firstName.setValidationVisible(true); 105 | lastName.setValidationVisible(true); 106 | patronymic.setValidationVisible(true); 107 | telephoneNumber.setValidationVisible(true); 108 | } 109 | 110 | private void configureComponentsValidators() { 111 | StringLengthValidator stringLengthValidator = 112 | new StringLengthValidator("Prompt is empty", 1, 50, false); 113 | telephoneNumber.addValidator(new LongRangeValidator("Value is negative", 0L, Long.MAX_VALUE)); 114 | firstName.addValidator(stringLengthValidator); 115 | lastName.addValidator(stringLengthValidator); 116 | patronymic.addValidator(stringLengthValidator); 117 | } 118 | 119 | private void configureComponentsWidth() { 120 | firstName.setWidth(String.valueOf(300)); 121 | lastName.setWidth(String.valueOf(300)); 122 | patronymic.setWidth(String.valueOf(300)); 123 | telephoneNumber.setWidth(String.valueOf(300)); 124 | } 125 | 126 | void actionAfterClickOkButton(Button.ClickEvent clickEvent) { 127 | patientVerticalLayout.disableButtons(); 128 | Patient patient = new Patient(firstName.getValue(), lastName.getValue(), patronymic.getValue(), 129 | Long.parseLong(telephoneNumber.getConvertedValue().toString())); 130 | try { 131 | PatientDao patientDao = DaoFactory.getInstance().getPatientDao(); 132 | if (selectedPatient == null) { 133 | patientDao.create(patient); 134 | } else { 135 | if (selectedPatient.getId() == null) { 136 | throw new IllegalArgumentException(); 137 | } 138 | patient.setId(selectedPatient.getId()); 139 | patientDao.update(patient); 140 | } 141 | getUI().getPrescriptionVerticalLayout().refreshGrid(null); 142 | getUI().getPrescriptionVerticalLayout().refreshPatientFilter(); 143 | patientVerticalLayout.refreshGrid(); 144 | close(); 145 | } catch (SQLException e) { 146 | Notification.show("Taking action for this patient is impossible!", "There are some problems with the database.", 147 | Notification.Type.ERROR_MESSAGE); 148 | } 149 | } 150 | 151 | private void actionAfterTextChangeEvent(FieldEvents.TextChangeEvent event, TextField textField) { 152 | textField.setValue(event.getText()); 153 | textField.setCursorPosition(event.getCursorPosition()); 154 | try { 155 | firstName.validate(); 156 | lastName.validate(); 157 | patronymic.validate(); 158 | telephoneNumber.validate(); 159 | okButton.setEnabled(true); 160 | } catch (Validator.InvalidValueException e) { 161 | okButton.setEnabled(false); 162 | } 163 | } 164 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/layout/PrescriptionVerticalLayout.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.layout; 2 | 3 | import com.zufar.testtask.hsqldb.dto.PersonFullName; 4 | import com.zufar.testtask.model.Prescription; 5 | import com.zufar.testtask.hsqldb.DaoFactory; 6 | import com.zufar.testtask.model.Priority; 7 | import com.zufar.testtask.ui.window.PrescriptionWindow; 8 | import com.vaadin.data.Property; 9 | import com.vaadin.data.util.BeanItemContainer; 10 | import com.vaadin.event.FieldEvents; 11 | import com.vaadin.server.FontAwesome; 12 | import com.vaadin.ui.*; 13 | 14 | import java.sql.SQLException; 15 | import java.util.List; 16 | 17 | public class PrescriptionVerticalLayout extends AbstractVerticalLayout { 18 | 19 | private TextField descriptionFilter = new TextField("Description:"); 20 | private NativeSelect patientFilter = new NativeSelect("Patient:"); 21 | private NativeSelect priorityFilter = new NativeSelect("Priority:"); 22 | private Button filterButton = new Button("Apply", clickEvent -> { 23 | try { 24 | List prescriptions = DaoFactory.getInstance().getPrescriptionDao().getAllByFilters( 25 | descriptionFilter.getValue(), (PersonFullName) patientFilter.getValue(), (Priority) priorityFilter.getValue()); 26 | refreshGrid(prescriptions); 27 | } catch (SQLException e) { 28 | Notification.show("Filtering is impossible!", "There are some problems with the database.", 29 | Notification.Type.ERROR_MESSAGE); 30 | } 31 | }); 32 | 33 | public PrescriptionVerticalLayout() { 34 | configureComponents(); 35 | } 36 | 37 | private void configureComponents() { 38 | buildLayout(); 39 | addButton.addClickListener(clickEvent -> UI.getCurrent().addWindow(new PrescriptionWindow(this, null))); 40 | editButton.addClickListener(clickEvent -> { 41 | if (grid.getSelectedRow() == null) { 42 | disableButtons(); 43 | } else { 44 | UI.getCurrent().addWindow(new PrescriptionWindow(this, (Prescription) grid.getSelectedRow())); 45 | } 46 | }); 47 | label.setValue("Prescription's list"); 48 | filterButton.setEnabled(false); 49 | filterButton.setIcon(FontAwesome.CHECK); 50 | configureFilterComponents(); 51 | disableButtons(); 52 | configureGrid(); 53 | refreshGrid(null); 54 | } 55 | 56 | private void buildLayout() { 57 | HorizontalLayout filterLayout = new HorizontalLayout(descriptionFilter, patientFilter, priorityFilter, filterButton); 58 | filterLayout.setMargin(true); 59 | filterLayout.setSpacing(true); 60 | filterLayout.setComponentAlignment(filterButton, Alignment.BOTTOM_RIGHT); 61 | Panel filterPanel = new Panel("Prescription's filter panel"); 62 | filterPanel.setContent(filterLayout); 63 | addComponents(label, filterPanel, grid, buttonsLayout); 64 | } 65 | 66 | private void configureFilterComponents() { 67 | descriptionFilter.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 68 | priorityFilter.addItems(Priority.NORMAL, Priority.SITO, Priority.STATIM); 69 | descriptionFilter.setInputPrompt("description"); 70 | priorityFilter.setValue(null); 71 | configureFilterComponentsImmediate(); 72 | configureFilterComponentsNullSelectionAllowed(); 73 | configureFilterComponentsActionListeners(); 74 | configureFilterComponentsNullSelectionItemIds(); 75 | configureFilterComponentsWidth(); 76 | configureFilterComponentsHeight(); 77 | refreshPatientFilter(); 78 | } 79 | 80 | private void configureFilterComponentsNullSelectionItemIds() { 81 | patientFilter.setNullSelectionItemId(""); 82 | priorityFilter.setNullSelectionItemId(""); 83 | } 84 | 85 | private void configureFilterComponentsActionListeners() { 86 | patientFilter.addValueChangeListener(event -> actionAfterSelectChangeEvent(event, patientFilter)); 87 | priorityFilter.addValueChangeListener(event -> actionAfterSelectChangeEvent(event, priorityFilter)); 88 | patientFilter.addContextClickListener(contextClickEvent -> refreshPatientFilter()); 89 | descriptionFilter.addTextChangeListener(event -> actionAfterTextChangeEvent(event, descriptionFilter)); 90 | } 91 | 92 | private void configureFilterComponentsNullSelectionAllowed() { 93 | patientFilter.setNullSelectionAllowed(true); 94 | priorityFilter.setNullSelectionAllowed(true); 95 | } 96 | 97 | private void configureFilterComponentsImmediate() { 98 | descriptionFilter.setImmediate(true); 99 | patientFilter.setImmediate(true); 100 | } 101 | 102 | private void configureFilterComponentsHeight() { 103 | descriptionFilter.setHeight("30"); 104 | patientFilter.setHeight("30"); 105 | priorityFilter.setHeight("30"); 106 | filterButton.setHeight("30"); 107 | } 108 | 109 | private void configureFilterComponentsWidth() { 110 | filterButton.setWidth("150"); 111 | descriptionFilter.setWidth("200"); 112 | patientFilter.setWidth("200"); 113 | priorityFilter.setWidth("200"); 114 | } 115 | 116 | private void configureGrid() { 117 | grid.setContainerDataSource(new BeanItemContainer<>(Prescription.class)); 118 | grid.setColumnOrder("description", "patient", "doctor", "creationDate", "validity", "priority"); 119 | grid.removeColumn("id"); 120 | grid.addSelectionListener(selectionEvent -> { 121 | deleteButton.setEnabled(true); 122 | editButton.setEnabled(true); 123 | }); 124 | } 125 | 126 | private void actionAfterTextChangeEvent(FieldEvents.TextChangeEvent event, TextField textField) { 127 | textField.setValue(event.getText()); 128 | textField.setCursorPosition(event.getCursorPosition()); 129 | if (patientFilter.isEmpty() && descriptionFilter.isEmpty() && priorityFilter.isEmpty()) { 130 | refreshGrid(null); 131 | filterButton.setEnabled(false); 132 | } else { 133 | filterButton.setEnabled(true); 134 | } 135 | } 136 | 137 | private void actionAfterSelectChangeEvent(Property.ValueChangeEvent event, NativeSelect select) { 138 | select.setValue(event.getProperty().getValue()); 139 | if (patientFilter.isEmpty() && descriptionFilter.isEmpty() && priorityFilter.isEmpty()) { 140 | refreshGrid(null); 141 | filterButton.setEnabled(false); 142 | } else { 143 | filterButton.setEnabled(true); 144 | } 145 | } 146 | 147 | public void refreshGrid(List filteredPrescriptions) { 148 | if (filteredPrescriptions != null) { 149 | grid.setContainerDataSource(new BeanItemContainer<>(Prescription.class, filteredPrescriptions)); 150 | return; 151 | } 152 | try { 153 | List prescriptions = DaoFactory.getInstance().getPrescriptionDao().getAll(); 154 | grid.setContainerDataSource(new BeanItemContainer<>(Prescription.class, prescriptions)); 155 | grid.setColumnOrder("description", "patient", "doctor", "creationDate", "validity", "priority"); 156 | } catch (SQLException e) { 157 | Notification.show("Refreshing the grid is impossible!", "There are some problems with the database.", 158 | Notification.Type.ERROR_MESSAGE); 159 | } 160 | } 161 | 162 | public void disableButtons() { 163 | deleteButton.setEnabled(false); 164 | editButton.setEnabled(false); 165 | } 166 | 167 | public boolean refreshPatientFilter() { 168 | try { 169 | patientFilter.removeAllItems(); 170 | patientFilter.setValue(null); 171 | List patientsFullNames = DaoFactory.getInstance().getPatientDao().getAllFullNames(); 172 | patientFilter.addItems(patientsFullNames); 173 | } catch (SQLException e) { 174 | return true; 175 | } 176 | return false; 177 | } 178 | 179 | @Override 180 | void actionAfterClickDeleteButton(Button.ClickEvent event) { 181 | disableButtons(); 182 | if (grid.getSelectedRow() == null) { 183 | return; 184 | } 185 | try { 186 | DaoFactory.getInstance().getPrescriptionDao().delete((Prescription) grid.getSelectedRow()); 187 | refreshGrid(null); 188 | } catch (SQLException e) { 189 | Notification.show("Deleting this prescription is impossible!", "There are some problems with the database.", 190 | Notification.Type.ERROR_MESSAGE); 191 | } 192 | } 193 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/hsqldb/PrescriptionDao.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.hsqldb; 2 | 3 | import com.zufar.testtask.dao.AbstractCrudDao; 4 | import com.zufar.testtask.hsqldb.dto.PersonFullName; 5 | import com.zufar.testtask.model.Prescription; 6 | import com.zufar.testtask.model.Priority; 7 | 8 | import java.sql.*; 9 | import java.sql.Date; 10 | import java.time.LocalDate; 11 | import java.time.format.DateTimeFormatter; 12 | import java.util.*; 13 | 14 | public class PrescriptionDao extends AbstractCrudDao { 15 | 16 | PrescriptionDao(Connection connection) { 17 | super(connection); 18 | } 19 | 20 | @Override 21 | public String getSelectQuery() { 22 | return " SELECT \n" + 23 | " PRESCRIPTION.id AS id, PRESCRIPTION.description AS description, PRESCRIPTION.creation_date AS creation_date, \n" + 24 | " PRESCRIPTION.validity AS validity, PRESCRIPTION.priority AS priority, PATIENT.id AS patientID,\n" + 25 | " PATIENT.first_name AS patientFirstName, PATIENT.last_name AS patientLastName, PATIENT.patronymic AS patientPatronymic,\n" + 26 | " DOCTOR.id AS doctorID, DOCTOR.first_name AS doctorFirstName, DOCTOR.last_name AS doctorLastName,\n" + 27 | " DOCTOR.patronymic AS doctorPatronymic FROM PRESCRIPTION JOIN PATIENT ON PRESCRIPTION.patient_id = PATIENT.id \n" + 28 | " JOIN DOCTOR ON PRESCRIPTION.doctor_id = DOCTOR.id"; 29 | } 30 | 31 | @Override 32 | public String getCreateQuery() { 33 | return "INSERT INTO PRESCRIPTION " + 34 | "(description, patient_id, doctor_id, creation_date, validity, priority) VALUES (?, ?, ?, ?, ?, ?)"; 35 | } 36 | 37 | @Override 38 | public String getUpdateQuery() { 39 | return "UPDATE PRESCRIPTION SET description = ?, patient_id = ?, doctor_id = ?, creation_date = ?," + 40 | " validity = ?, priority = ? WHERE id = ?"; 41 | } 42 | 43 | @Override 44 | public String getDeleteQuery() { 45 | return "DELETE FROM PRESCRIPTION WHERE id= ?"; 46 | } 47 | 48 | @Override 49 | protected List parseResultSet(ResultSet resultSet) throws SQLException { 50 | List prescriptions = new ArrayList<>(); 51 | while (resultSet.next()) { 52 | Long id = (resultSet.getLong("id")); 53 | String description = (resultSet.getString("description")); 54 | PersonFullName patientFullName = new PersonFullName( 55 | resultSet.getLong("patientID"), 56 | resultSet.getString("patientFirstName"), 57 | resultSet.getString("patientLastName"), 58 | resultSet.getString("patientPatronymic") 59 | ); 60 | PersonFullName doctorFullName = new PersonFullName( 61 | resultSet.getLong("doctorID"), 62 | resultSet.getString("doctorFirstName"), 63 | resultSet.getString("doctorLastName"), 64 | resultSet.getString("doctorPatronymic") 65 | ); 66 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 67 | LocalDate creationDate = LocalDate.parse(resultSet.getDate("creation_date").toLocalDate().format(formatter)); 68 | Long validity = resultSet.getLong("validity"); 69 | Priority priority = Priority.valueOf(resultSet.getString("priority")); 70 | Prescription prescription = new Prescription(id, description, patientFullName, doctorFullName, creationDate, validity, priority); 71 | prescriptions.add(prescription); 72 | } 73 | return prescriptions; 74 | } 75 | 76 | @Override 77 | protected void prepareStatementForUpdate(PreparedStatement preparedStatement, Prescription prescription) throws SQLException { 78 | if (prescription.getId() == null || prescription.getDescription() == null || prescription.getPatient() == null || 79 | prescription.getPatient().getId() == null || prescription.getDoctor() == null || 80 | prescription.getDoctor().getId() == null || prescription.getCreationDate() == null || 81 | prescription.getValidity() == null || prescription.getPriority() == null) { 82 | throw new IllegalArgumentException("Some prescription object's fields are absent!"); 83 | } 84 | preparedStatement.setString(1, prescription.getDescription()); 85 | preparedStatement.setLong(2, prescription.getPatient().getId()); 86 | preparedStatement.setLong(3, prescription.getDoctor().getId()); 87 | preparedStatement.setDate(4, Date.valueOf(prescription.getCreationDate())); 88 | preparedStatement.setLong(5, prescription.getValidity()); 89 | preparedStatement.setString(6, prescription.getPriority().toString()); 90 | preparedStatement.setLong(7, prescription.getId()); 91 | } 92 | 93 | @Override 94 | protected void prepareStatementForInsert(PreparedStatement preparedStatement, Prescription prescription) 95 | throws SQLException, IllegalArgumentException { 96 | if (prescription.getDescription() == null || prescription.getPatient() == null || 97 | prescription.getPatient().getId() == null || prescription.getDoctor() == null || 98 | prescription.getDoctor().getId() == null || prescription.getCreationDate() == null || 99 | prescription.getValidity() == null || prescription.getPriority() == null) { 100 | throw new IllegalArgumentException("Some prescription object's fields are absent!"); 101 | } 102 | preparedStatement.setString(1, prescription.getDescription()); 103 | preparedStatement.setLong(2, prescription.getPatient().getId()); 104 | preparedStatement.setLong(3, prescription.getDoctor().getId()); 105 | preparedStatement.setDate(4, Date.valueOf(prescription.getCreationDate())); 106 | preparedStatement.setLong(5, prescription.getValidity()); 107 | preparedStatement.setString(6, prescription.getPriority().toString()); 108 | } 109 | 110 | public List getAllByFilters(String descriptionFilter, PersonFullName patientFilter, Priority priorityFilter) 111 | throws SQLException { 112 | StringBuilder filteredSelectQuery = new StringBuilder(getSelectQuery()); 113 | List whereConditions = new ArrayList<>(); 114 | if (descriptionFilter != null && !descriptionFilter.isEmpty()) { 115 | filteredSelectQuery.append(" AND description LIKE ? "); 116 | whereConditions.add("%" + descriptionFilter + "%"); 117 | } 118 | if (patientFilter != null && patientFilter.getId() != null) { 119 | filteredSelectQuery.append(" AND Patient.id = ? "); 120 | whereConditions.add(patientFilter.getId().toString()); 121 | } 122 | if (priorityFilter != null) { 123 | filteredSelectQuery.append(" AND priority = ? "); 124 | whereConditions.add(priorityFilter.name()); 125 | } 126 | PreparedStatement preparedStatement = connection.prepareStatement(filteredSelectQuery.toString()); 127 | for (int i = 0; i < whereConditions.size(); i++) { 128 | preparedStatement.setString(i + 1, whereConditions.get(i)); 129 | } 130 | ResultSet resultSet = preparedStatement.executeQuery(); 131 | List prescriptions = new ArrayList<>(); 132 | while (resultSet.next()) { 133 | Long id = resultSet.getLong("id"); 134 | String description = resultSet.getString("description"); 135 | PersonFullName patientFullName = new PersonFullName( 136 | resultSet.getLong("PatientID"), 137 | resultSet.getString("patientFirstName"), 138 | resultSet.getString("patientLastName"), 139 | resultSet.getString("patientPatronymic") 140 | ); 141 | PersonFullName doctorFullName = new PersonFullName( 142 | resultSet.getLong("PatientID"), 143 | resultSet.getString("doctorFirstName"), 144 | resultSet.getString("doctorLastName"), 145 | resultSet.getString("doctorPatronymic") 146 | ); 147 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 148 | LocalDate creationDate = LocalDate.parse(resultSet.getDate("creation_date").toLocalDate().format(formatter), formatter); 149 | Long validity = resultSet.getLong("validity"); 150 | Priority priority = Priority.valueOf(resultSet.getString("priority")); 151 | prescriptions.add(new Prescription(id, description, patientFullName, doctorFullName, creationDate, validity, priority)); 152 | } 153 | return prescriptions; 154 | } 155 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/testtask/ui/window/PrescriptionWindow.java: -------------------------------------------------------------------------------- 1 | package com.zufar.testtask.ui.window; 2 | 3 | import com.zufar.testtask.hsqldb.PrescriptionDao; 4 | import com.vaadin.data.util.converter.StringToDateConverter; 5 | import com.zufar.testtask.hsqldb.dto.PersonFullName; 6 | import com.zufar.testtask.model.Prescription; 7 | import com.zufar.testtask.hsqldb.DaoFactory; 8 | import com.zufar.testtask.model.Priority; 9 | import com.zufar.testtask.ui.layout.PrescriptionVerticalLayout; 10 | import com.vaadin.data.Property; 11 | import com.vaadin.data.Validator; 12 | import com.vaadin.data.util.converter.StringToLongConverter; 13 | import com.vaadin.data.validator.DateRangeValidator; 14 | import com.vaadin.data.validator.LongRangeValidator; 15 | import com.vaadin.data.validator.StringLengthValidator; 16 | import com.vaadin.event.FieldEvents; 17 | import com.vaadin.shared.ui.datefield.Resolution; 18 | import com.vaadin.ui.*; 19 | 20 | import java.sql.SQLException; 21 | import java.time.ZoneId; 22 | import java.util.*; 23 | 24 | public class PrescriptionWindow extends AbstractWindow { 25 | 26 | private TextField description = new TextField("Description:"); 27 | private NativeSelect selectPatient = new NativeSelect("Patient:"); 28 | private NativeSelect selectDoctor = new NativeSelect("Doctor:"); 29 | private DateField creationDate = new DateField("Creation's date:", new Date()); 30 | private TextField validity = new TextField("Validity (day's count):"); 31 | private NativeSelect selectPriority = new NativeSelect("Priority:"); 32 | private PrescriptionVerticalLayout prescriptionVerticalLayout; 33 | private Prescription selectedPrescription; 34 | 35 | public PrescriptionWindow(PrescriptionVerticalLayout prescriptionVerticalLayout, Prescription selectedPrescription) { 36 | this.prescriptionVerticalLayout = prescriptionVerticalLayout; 37 | this.selectedPrescription = selectedPrescription; 38 | this.verticalFields.addComponents(description, selectPatient, selectDoctor, creationDate, validity, selectPriority); 39 | configureComponents(); 40 | } 41 | 42 | private void configureComponents() { 43 | description.focus(); 44 | validity.setNullSettingAllowed(false); 45 | configureComponentsNullRepresentation(); 46 | configureComponentsNullSellectionAllowed(); 47 | configureComponentsWidth(); 48 | configureComponentsValidators(); 49 | configureComponentsValidationVisibility(); 50 | configureComponentsRequired(); 51 | configureComponentsTextChangeEventMode(); 52 | configureComponentsChangeListeners(); 53 | configureComponentsMaxLength(); 54 | configureComponentsConverters(); 55 | configureComponentsImmediate(); 56 | configureComponentsValue(); 57 | } 58 | 59 | private void configureComponentsNullRepresentation() { 60 | validity.setNullRepresentation(""); 61 | description.setNullRepresentation(""); 62 | } 63 | 64 | private void configureComponentsNullSellectionAllowed() { 65 | selectPatient.setNullSelectionAllowed(false); 66 | selectDoctor.setNullSelectionAllowed(false); 67 | selectPriority.setNullSelectionAllowed(false); 68 | } 69 | 70 | private void configureComponentsValue() { 71 | List patients; 72 | List doctors; 73 | try { 74 | patients = DaoFactory.getInstance().getPatientDao().getAllFullNames(); 75 | selectPatient.addItems(patients); 76 | if (!patients.isEmpty()) { 77 | for (PersonFullName patient : patients) { 78 | if (patient != null) { 79 | selectPatient.setValue(patient); 80 | break; 81 | } 82 | 83 | } 84 | } 85 | doctors = DaoFactory.getInstance().getDoctorDao().getAllFullNames(); 86 | selectDoctor.addItems(doctors); 87 | if (!doctors.isEmpty()) { 88 | for (PersonFullName doctor : doctors) { 89 | if (doctor != null) { 90 | selectDoctor.setValue(doctor); 91 | break; 92 | } 93 | } 94 | } 95 | selectPriority.addItems(Priority.NORMAL, Priority.SITO, Priority.STATIM); 96 | selectPriority.setValue(Priority.NORMAL); 97 | } catch (SQLException e) { 98 | prescriptionVerticalLayout.disableButtons(); 99 | close(); 100 | return; 101 | } 102 | //Если передан selectedPrescription, значит устанавливаем значения для окна EditPrescription 103 | if (selectedPrescription != null) { 104 | if (selectedPrescription.getCreationDate() == null || selectedPrescription.getValidity() == null || 105 | selectedPrescription.getPatient() == null || selectedPrescription.getPatient().getId() == null || 106 | selectedPrescription.getDoctor() == null || selectedPrescription.getDoctor().getId() == null) { 107 | throw new IllegalArgumentException("Some selectedRow's fields are absent!"); 108 | } 109 | PersonFullName patient = patients.stream(). 110 | filter(p -> Objects.equals(p.getId(), selectedPrescription.getPatient().getId())).findFirst().get(); 111 | PersonFullName doctor = doctors.stream(). 112 | filter(d -> Objects.equals(d.getId(), selectedPrescription.getDoctor().getId())).findFirst().get(); 113 | selectPatient.setValue(patient); 114 | selectDoctor.setValue(doctor); 115 | description.setValue(selectedPrescription.getDescription()); 116 | creationDate.setValue(Date.from(selectedPrescription.getCreationDate().atStartOfDay(ZoneId.systemDefault()).toInstant())); 117 | validity.setValue(selectedPrescription.getValidity().toString()); 118 | selectPriority.setValue(selectedPrescription.getPriority()); 119 | } 120 | } 121 | 122 | private void configureComponentsImmediate() { 123 | description.setImmediate(true); 124 | validity.setImmediate(true); 125 | creationDate.setImmediate(true); 126 | } 127 | 128 | private void configureComponentsConverters() { 129 | validity.setConverter(new StringToLongConverter()); 130 | creationDate.setConverter(new StringToDateConverter().getModelType()); 131 | } 132 | 133 | private void configureComponentsMaxLength() { 134 | description.setMaxLength(50); 135 | validity.setMaxLength(18); 136 | } 137 | 138 | private void configureComponentsChangeListeners() { 139 | selectPriority.addValueChangeListener(event -> actionAfterSelectChangeEvent(event, selectPriority)); 140 | selectPatient.addValueChangeListener(event -> actionAfterSelectChangeEvent(event, selectPatient)); 141 | selectDoctor.addValueChangeListener(event -> actionAfterSelectChangeEvent(event, selectDoctor)); 142 | description.addTextChangeListener(event -> actionAfterTextChangeEvent(event, description)); 143 | validity.addTextChangeListener(event -> actionAfterTextChangeEvent(event, validity)); 144 | creationDate.addValueChangeListener(event -> actionAfterDateChangeEvent()); 145 | } 146 | 147 | private void configureComponentsTextChangeEventMode() { 148 | description.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 149 | validity.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER); 150 | } 151 | 152 | private void configureComponentsRequired() { 153 | selectPriority.setRequired(true); 154 | selectPatient.setRequired(true); 155 | selectDoctor.setRequired(true); 156 | description.setRequired(true); 157 | validity.setRequired(true); 158 | } 159 | 160 | private void configureComponentsValidationVisibility() { 161 | description.setValidationVisible(true); 162 | validity.setValidationVisible(true); 163 | selectPatient.setValidationVisible(true); 164 | selectDoctor.setValidationVisible(true); 165 | selectPriority.setValidationVisible(true); 166 | creationDate.setValidationVisible(true); 167 | } 168 | 169 | private void configureComponentsValidators() { 170 | validity.addValidator(new LongRangeValidator("Negative value in field!", 0L, Long.MAX_VALUE)); 171 | creationDate.addValidator(new DateRangeValidator("Wrong date!", null, null, Resolution.DAY)); 172 | description.addValidator(new StringLengthValidator("Field is empty!", 1, 50, false)); 173 | } 174 | 175 | private void configureComponentsWidth() { 176 | selectPriority.setWidth("300"); 177 | selectPatient.setWidth("300"); 178 | creationDate.setWidth("300"); 179 | selectDoctor.setWidth("300"); 180 | description.setWidth("300"); 181 | validity.setWidth("300"); 182 | } 183 | 184 | void actionAfterClickOkButton(Button.ClickEvent clickEvent) { 185 | prescriptionVerticalLayout.disableButtons(); 186 | Prescription prescription = new Prescription( 187 | description.getValue(), 188 | ((PersonFullName) selectPatient.getValue()), 189 | ((PersonFullName) selectDoctor.getValue()), 190 | creationDate.getValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), 191 | (Long) validity.getConvertedValue(), 192 | Priority.valueOf(selectPriority.getValue().toString()) 193 | ); 194 | try { 195 | PrescriptionDao prescriptionDao = DaoFactory.getInstance().getPrescriptionDao(); 196 | if (selectedPrescription == null) { 197 | prescriptionDao.create(prescription); 198 | } else { 199 | if (selectedPrescription.getId() == null) { 200 | throw new IllegalArgumentException(); 201 | } 202 | prescription.setId(selectedPrescription.getId()); 203 | prescriptionDao.update(prescription); 204 | } 205 | getUI().getPrescriptionVerticalLayout().refreshGrid(null); 206 | prescriptionVerticalLayout.refreshGrid(null); 207 | close(); 208 | } catch (SQLException e) { 209 | Notification.show("Taking action for this prescription is impossible!", "There are some problems with the database.", 210 | Notification.Type.ERROR_MESSAGE); 211 | } 212 | } 213 | 214 | private void actionAfterTextChangeEvent(FieldEvents.TextChangeEvent event, TextField textField) { 215 | textField.setValue(event.getText()); 216 | textField.setCursorPosition(event.getCursorPosition()); 217 | enableButtonByValidityComponents(); 218 | } 219 | 220 | private void actionAfterSelectChangeEvent(Property.ValueChangeEvent event, NativeSelect select) { 221 | select.setValue(event.getProperty().getValue()); 222 | enableButtonByValidityComponents(); 223 | } 224 | 225 | private void actionAfterDateChangeEvent() { 226 | if (creationDate.isEmpty()) { 227 | if (selectedPrescription != null && selectedPrescription.getCreationDate() != null) { 228 | creationDate.setValue(Date.from(selectedPrescription.getCreationDate().atStartOfDay(ZoneId.systemDefault()).toInstant())); 229 | } else { 230 | creationDate.setValue(new Date()); 231 | } 232 | } 233 | enableButtonByValidityComponents(); 234 | } 235 | 236 | private void enableButtonByValidityComponents() { 237 | if (description.getValue() == null || description.getValue().isEmpty() || 238 | selectPatient.getValue() == null || selectPatient.getValue().toString().isEmpty() || 239 | selectDoctor.getValue() == null || selectDoctor.getValue().toString().isEmpty() || 240 | creationDate.getValue() == null || creationDate.getValue().toString().isEmpty() || 241 | selectPriority.getValue() == null || selectPriority.getValue().toString().isEmpty()) { 242 | okButton.setEnabled(false); 243 | return; 244 | } 245 | try { 246 | creationDate.validate(); 247 | description.validate(); 248 | validity.validate(); 249 | okButton.setEnabled(true); 250 | } catch (Validator.InvalidValueException e) { 251 | okButton.setEnabled(false); 252 | } 253 | } 254 | } --------------------------------------------------------------------------------