I am developing an application for didactic purposes, college end of semester work, in this will do CRUD of the disciplines in a table in the already created bank, "DISCIPLINES" , I thought about creating a list of processes, if you want to redo your changes, type crt + z, it is after making the changes and be certain of this, execute the changes. this way:
The user does a crud operation through the graphical interface, and after the changes, clicking OK executes the list of processes. follows the method code that generates, deletes, and executes processes:
//Implentação da interface omitidos
@Override
public void setupEvents() {
//evento do botão deletar disciplina
btnDelete.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int rowIndex = tbListDisciplines.getSelectedRow();
int id = (int)tbListDisciplines.getModel().getValueAt(rowIndex, 0);
InvokerRemove delete = new InvokerRemove(id, new ControllerDiscipline());
queue.addProcess(delete);
lblAmountDisciplines.setText("" + tbListDisciplines.getRowCount());
model.remove(rowIndex);
}
});
//evento do botão alterar disciplina
btnEdit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int rowIndex = tbListDisciplines.getSelectedRow();
int id = (int)tbListDisciplines.getModel().getValueAt(rowIndex, 0);
String name = tfNameDiscipline.getText();
InvokerUpdateRefatorar update = new InvokerUpdateRefatorar(id, name, new ControllerDiscipline());
queue.addProcess(update);
System.out.println(name);
Discipline marca = new Discipline();
marca.setName(tfNameDiscipline.getText());
model.update(rowIndex, marca);
}
});
//evento que finaliza as alterações e executa os processos de crud.
btnOk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
glassPanel.start();
queue.executeProcess();
model.clearlistRemoved();
Thread performer = new Thread(new Runnable() {
public void run() {
perform();
}
}, "Performer");
performer.start();
}
});
//evento do botão cancelar, e invoca o método sair.
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
quit();
}
});
//MouseListener para preencher o textField
tbListDisciplines.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int rowIndex = tbListDisciplines.getSelectedRow();
tfNameDiscipline.setText((String)tbListDisciplines.getModel().getValueAt(rowIndex, 1));
}
});
}
//outros métodos omitidos
If you want to undo the change, it clicks cancel (I'm still implementing a better way to do this, for example, crt + z to undo the last change)
@Override
public void quit() {
if(!model.isEmptyList()){
int confirm = JOptionPane.showConfirmDialog(this, "Deseja sair, as alterações feita não serão salvas ?",
"Desistir das alterações?", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
if(confirm == JOptionPane.YES_OPTION) {
this.dispose();
model.clearlistRemoved();
}
} else{
this.dispose();
}
}
Just for the sake of beauty I've added a glassPane to simulate a very simple thing.
In the question of generating the list of processes I'm using the Pattern Command, create a process queue, QueuesProcess , which will be responsible for receiving all "crud operations" follows the code: / p>
/**
* Classe responsável por criar uma fila de processos, CRUD,
* remove processos da fila para casos de refazer as decisões anteriores
* e limpa a fila para os próximos processos.
* <br><br>
* Nome do projeto: MeOrganize <br>
* Integra ao pocote: utfpr.tsi.meOrganize.controller.impl<br>
* @author Vinicius Cavalcanti
* @since implementação da aplicação
* @version 1.0v 2016
*/
public class QueuesProcess {
private Queue<IECommand> process;
/**
* construtor inicializa a lista de processos
*/
public QueuesProcess() {
process = new LinkedList();
}
/**
* Método que adiciona processos a lista
* @param process - o processo que será adicionado a fila
*/
public void addProcess(IECommand process) {
this.process.add(process);
}
/**
* Método que remove um processo adicionado
* @param process - processo que será removido
*/
public void removeProcess(IECommand process) {
this.process.remove(process);
}
/**
* Método que limpa a lista para casos
* de sair da janela e cancelar as operações (CRUD)
*/
public void clearQueues() {
this.process.clear();
}
/**
* Método que executa as operações na fila e limpa a fila.
*/
public void executeProcess() {
for(IECommand command : this.process)
command.execute();
process.clear();
}
}
As I said I'm using the pattern command, so I created an IEcommand interface for the invoker contract with just the execute command. Dry the code below:
/**
* Contrato da fila de comandos CRUD.
* <br><br>
* Nome do projeto: MeOrganize <br>
* Integra ao pocote: utfpr.tsi.meOrganize.controller<br>
* @author Vinicius Cavalcanti
* @since
* @version 2016
*/
public interface IECommand {
void execute();
}
And an abstract class for crud requests, I'm going to create a controller for each table, in this case I'm showing only the disciplines, but it will have other entities, such as the study schedule, planning. >
/**
* Classe abstrata responsável pelos pedidos de Crud
* para camada dao, antes de inserir faz uma busca no banco
* para verificar se a entidade já existe e retonar o resultado.
* <br><br>
* Nome do projeto: MeOrganize <br>
* Integra ao pocote: utfpr.tsi.meOrganize.controller.impl<br>
* @author Vinicius Cavalcanti
* @since implentação da aplicação
* @version 1.0c 2016
* @param <T> entidade
* @param <E> qual dao será utilizado.
*/
public abstract class Controller<T, E> implements IERegister<T, E>{
protected IEDAO dao;
protected IEEntity entity;
public Controller(IEDAO dao, IEEntity entity) {
this.dao = dao;
this.entity = entity;
}
/**
* Método responsável por pedir a camada dao a inserção
* na tabela da entidade.
* @return - retorna true se a inserção foi feita, false se não é o erro.
* @throws - erro se a entidade veio nula.
*/
public boolean add(String name) throws EntityNull {
this.entity.setName(name);
if(exists() == false) {
try {
dao.insert(entity);
} catch (EntityNull | ClassNotFoundException e) {
System.out.println("Não foi possivel adicionar ao banco porque:\n" + e.getMessage());
}
return true;
}
return false;
}
/**
* Método responsável por pedir a remoção da entidade da tabela.
* A remoção e feita por uma busca pelo id da entidade.
* @return - retorna true se a remoção foi feita, false se não é o erro.
* @throws - erro se a entidade veio nula.
*/
public boolean remove(int id) throws EntityNull{
try {
this.dao.remove(id);
} catch (EntityNull | ClassNotFoundException e) {
System.out.println("Não foi possível remover porque:\n" + e.getMessage());
}
return false;
}
/**
* Método responsável por pedir a camada dao a alteração na entidade.
* faz uma busca pelo id da entidade e pede a alteração.
* @throws - erro se a entidade veio nula.
*/
public void update(int id, String name) throws EntityNull{
this.entity.setId(id);
this.entity.setName(name);
try {
this.dao.update(entity);
} catch (ClassNotFoundException e) {
System.out.println("Não foi possivel atualizar a entidade no banco porque:\n" + e.getMessage());
}
}
/**
* Método que verifica se a entidade já existe na tabale.
* faz uma busca na tabela pela entidade
* @return true se a entidade já existe, falso se não.
*/
public boolean exists() {
ArrayList<IEEntity<T>> entitys = new ArrayList<>();
try {
entitys.addAll(dao.searchData());
} catch (ClassNotFoundException e) {
System.out.println("Não foi possivel fazer a busca no banco porque:\n" + e.getMessage());
}
for(IEEntity enti : entitys) {
if(entity.getName().equals(enti.getName())) {
JOptionPane.showMessageDialog(null, "Entidade já existe", "Erro no cadastro da entidade", JOptionPane.ERROR_MESSAGE);
return true;
}
}
return false;
}
}
/**
* Contrato de controller das classe que recebe os dados
* para envidar para a camada DAO para manipular os dados das entidadades
* do banco de dados.
* <br><br>
* Nome do projeto: MeOrganize <br>
* Integra ao pocote: utfpr.tsi.meOrganize.controller<br>
* @author Vinicius Cavalcanti
* @since implementação da aplicação
* @version 1.0v 2016
* @param <T> Entidade que será passado para camada DAO.
* @param <E> Dao que será utilizado para entidade.
*/
public interface IERegister<T, E> {
/**
* Método responsável para enviar a camada DAO a entidade para salvar
* @param obj a entidade
* @throws EntityNull exceção de entidade nula.
*/
boolean add(String name) throws EntityNull;
/**
* Método responsável para enviar a camada DAO a entidade, por parâmetro o id,
* que será deletado.
* @param id - O id da entidade
* @throws EntityNull exceção de entidade nula.
*/
boolean remove(int id) throws EntityNull;
/**
* Método que verifica se a entidade já existe ou não
* @param dao
* @param entity
* @return true para existe e false para não existe.
*/
boolean existsDiscipline(T dao, E entity);
/**
* Método responsável para enviar a camada DAO a entidade, por parâmentro o id,
* que será alterado.
* @param id - O id da entidade.
* @throws EntityNull exceção de entidade nula.
*/
void update(int id, String name) throws EntityNull;
}
Another class that inherits the methods of the abstract class to do the crud, in this case of the disciplines.
/**
* Classe concreta responsável por gerenciar os pedidos de crud
* para camada dao.
* <br><br>
* Nome do projeto: MeOrganize <br>
* Integra ao pocote: utfpr.tsi.meOrganize.controller.impl<br>
* @author Vinicius Cavalcanti
* @since implementação da aplicação
* @version 1.0v 2016
*/
public class ControllerDiscipline extends Controller{
/**
* construtor que manda para super classe um
* entidade criada pelo dao.
*/
public ControllerDiscipline() {
super(new DisciplineDAO(), new DisciplineDAO().create());
}
/**
* Método que faz a inserção.
* @return true se inserção bem sucedida false se não.
* @throws - exceção se a entidade está nula
*/
public boolean add(String name) throws EntityNull{
return super.add(name);
}
/**
* Método que faz a remoção.
* @return true se remoção bem sucedida false se não.
* @throws - exceção se a entidade está nula
*/
public boolean remove(int id) throws EntityNull{
return super.remove(id);
}
/**
* Método que faz a alteração.
* @return true se alteração bem sucedida false se não.
* @throws - exceção se a entidade está nula
*/
public void update(int id, String name) throws EntityNull {
super.update(id, name);
}
/**
* Método que verifica se a entidade já existe.
* @return true se sim. false se não.
*/
@Override
public boolean existsDiscipline(Object dao, Object entity) {
return false;
}
}
Well explained the context. Now it comes to my doubt if I'm doing it right, because our teacher will evaluate the elegance of the code too, not just be working, the work "system" should be well written, with moderate use of patterns and a good structure. I created a class for each crud (InvokerAdd, IinvokerRemove, InvokerUpdate) as you can see in the interface code, I create a remove, and instantiate in the queue.
btnDelete.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int rowIndex = tbListDisciplines.getSelectedRow();
int id = (int)tbListDisciplines.getModel().getValueAt(rowIndex, 0);
InvokerRemove delete = new InvokerRemove(id, new ControllerDiscipline());
queue.addProcess(delete);
lblAmountDisciplines.setText("" + tbListDisciplines.getRowCount());
model.remove(rowIndex);
}
});
The queue of processes is popular. with only one method. I'm just posting to add but, it fits all, only changes are the parameters, in I thought of doing an overload of methods by changing the parameters, not whenever I add a new "method" I'm breaking the principle (OpenClose) of solid ?
Could you advise me on a better implementation?