package com.im.imjutil.transaction;
import java.util.ArrayList;
import java.util.List;
import com.im.imjutil.exception.TransactionException;
import com.im.imjutil.exception.ValidationException;
/**
* Classe que define uma transacao no sistema.
* Esta e composta de varias {@link Action} que
* definem a funcionalidade da transacao.
* <br>
* Apos instanciar uma {@link Transaction} deve-se adicionar e remover
* as {@link Action} desejadas.
* <br>
* O algoritmo de execucao deve estar de acordo com o exemplo abaixo:
* <br>
* <pre>
* <code>
* Transaction t = new Transaction();
* try {
* t.begin();
* t.add(new Action());
* t.remove(new Action());
* t.add(new Action());
* t.commit();
* } catch (TransactionException e) {
* t.rollback();
* } finally {
* if (t.isActive()) {
* t.rollback();
* }
* }
* </code>
* </pre>
*
* @author Bruno Alcantara
* @author Felipe Zappala
*/
public class Transaction {
/** Lista de acoes da transacao. */
private List<Action> actions;
/** Controla o inicio e fim da transacao. */
private boolean active;
/** Indice de execucao */
private int index;
/**
* Construtor padrao para uma transacao {@link Transaction}.
*/
public Transaction() {
this.setCollection(new ArrayList<Action>());
this.setInactive();
this.index = 0;
}
/**
* Verifica se a transacao esta ativa, ou seja, ainda nao foi finalizada.
*
* @return O estado da transacao.
*/
public boolean isActive() {
return this.active;
}
/**
* Habilita a transacao para execucao. Apos ativada,
* nao sera possivel adicionar novas acoes.
*
* @throws TransactionException caso ja estiver ativa.
*/
public void begin() throws TransactionException {
if (active) {
throw new TransactionException("A transacao ja esta ativa");
}
this.setActive();
}
/**
* Adiciona uma acao {@link Action} na transacao.
*
* @param action Uma acao da transacao.
* @throws ValidationException caso a acao for nula.
* @throws TransactionException caso a transacao nao estiver ativa.
*/
public void add(Action action) {
if (!active) {
throw new TransactionException(
"Nao e possivel adicionar acoes em uma transacao inativa");
}
if (action == null) {
throw new ValidationException("O parametro action e nulo");
}
actions.add(action);
}
/**
* Remove uma acao {@link Action} da transacao.
*
* @param action Uma acao da transacao.
* @throws ValidationException caso a acao for nula.
* @throws TransactionException caso a transacao nao estiver ativa.
*/
public void remove(Action action) {
if (!active) {
throw new TransactionException(
"Nao e possivel remover acoes em uma transacao inativa");
}
if (action == null) {
throw new ValidationException("O parametro action e nulo");
}
actions.remove(action);
}
/**
* Executa as {@link Action} da transacao.
*
* @throws Exception caso ocorra algum erro.
*/
public void commit() throws TransactionException {
if (!active) {
throw new TransactionException(
"Nao e possivel cometer uma transacao inativa");
}
for (Action action : actions) {
action.execute();
++index;
}
this.setInactive();
}
/**
* Desfaz as {@link Action} da transacao.
*
* @throws Exception caso ocorra algum erro.
*/
public void rollback() throws TransactionException {
if (!active) {
throw new TransactionException(
"Nao e possivel reverter uma transacao inativa");
}
for (int i = index; i >= 0 ; --i) {
actions.get(i).undo();
}
index = 0;
this.setInactive();
}
/**
* Configura a transacao como inativa.
*/
protected void setInactive() {
this.active = false;
}
/**
* Configura a transacao como ativa.
*/
protected void setActive() {
this.active = true;
}
/**
* Configura a colecao de armazenamento das acoes da transacao.
*
* @param collection Uma colecao para armazenamento das {@link Action}.
*/
protected void setCollection(List<Action> collection) {
if (collection == null) {
throw new ValidationException("A colecao passada e nula");
}
this.actions = collection;
}
}