src/br/usp/ime/academicdevoir/entidade/Resposta.java
@Embeddable
public class Resposta {
    @Column(length = Constantes.MAX_TAM_CAMPO)
	private String valor;
	
    @Min(0)
    @Max(100)
	private Double nota;
	
    @Column(length = Constantes.MAX_TAM_CAMPO)
	private String comentario;
	
    private String caminhoParaDiretorioDeTeste;
    
    /**
	 * @uml.property  name="questao"
	 * @uml.associationEnd  
	 */
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "questao_id")
	@Fetch(FetchMode.JOIN)
	@Cascade(CascadeType.SAVE_UPDATE)
	private Questao questao;
	
	public Questao getQuestao() {
		return questao;
	}

	public void setQuestao(Questao questao) {
		this.questao = questao;
	}

	public String getValor() {
		return valor;
	}

	public void setValor(String valor) {
		this.valor = valor;
	}

	public Double getNota() {
		return nota;
	}

	public void setNota(Double nota) {
		this.nota = nota;
	}
	
    public String getComentario() {
        return comentario;
    }

    public void setComentario(String comentario) {
        this.comentario = comentario;
    }
    
    public void setCaminhoParaDiretorioDeTeste(String caminhoParaDiretorioDeTeste) {
        this.caminhoParaDiretorioDeTeste = caminhoParaDiretorioDeTeste;
    }

    public String getCaminhoParaDiretorioDeTeste() {
        return caminhoParaDiretorioDeTeste;
    }

}
src/br/usp/ime/academicdevoir/dao/QuestaoDao.java
@Component
public class QuestaoDao {

	/**
	 * @uml.property name="session"
	 * @uml.associationEnd multiplicity="(0 -1)"
	 *                     elementType="br.usp.ime.academicdevoir.entidade.Questao"
	 */
	private final Session session;

	public QuestaoDao(Session session) {
		this.session = session;
	}

	@SuppressWarnings("unchecked")
	/**
	 * Devolve uma lista com todas as questões cadastradas no banco de dados.
	 * 
	 * @return List<Questao>
	 */
	public List<Questao> listaTudo() {
		return this.session.createCriteria(Questao.class).list();
	}
	
	/**
	 * Devolve uma lista com todas as questões cadastradas de acordo com a página.
	 * 
	 * @return List<Questao>
	 */
	private Criteria listaFiltrada(String filtro) {
		Criteria criteria = this.session.createCriteria(Questao.class);
		if (filtro != null && filtro != "")
			criteria.createCriteria("tags").add(Restrictions.ilike("nome", filtro, MatchMode.ANYWHERE));		
		return criteria;
	}

	/**
	 * Devolve o tamanho da lista com todas as questões cadastradas no banco de
	 * dados.
	 * 
	 * @return List<Questao>
	 */
	public Integer tamanhoDaLista(String filtro) {
		return listaFiltrada(filtro).list().size();
	}

	@SuppressWarnings("unchecked")
	/**
	 * Devolve uma lista com todas as questões cadastradas de acordo com a página.
	 * 
	 * @return List<Questao>
	 */
	public List<Questao> listaPaginada(Integer primeiro, Integer numRegistros,
			String filtro) {
		Criteria criteria = listaFiltrada(filtro);
		criteria.setFirstResult(primeiro);
		criteria.setMaxResults(numRegistros);
		return criteria.list();
	}

	/**
	 * Devolve uma questão com o id fornecido.
	 * 
	 * @param id
	 * @return Questao
	 */
	public Questao carrega(Long id) {
		return (Questao) this.session.load(Questao.class, id);
	}

	/**
	 * Remove a questão fornecida do banco de dados.
	 * 
	 * @param questao
	 */
	public void remove(Questao questao) {
		Transaction tx = session.beginTransaction();
		this.session.delete(questao);
		tx.commit();
	}

	/**
	 * Devolve uma Questao com o id fornecido, se existir. Caso contrário,
	 * retorna null.
	 * 
	 * @param id
	 * @return Questao
	 */
	public Questao busca(Long id) {
		return (Questao) session.createCriteria(Questao.class)
				.add(Restrictions.idEq(id)).uniqueResult();
	}

	public void recarrega(Questao questao) {
		session.refresh(questao);
	}
}
src/br/usp/ime/academicdevoir/infra/VerificadorDePrazos.java
public class VerificadorDePrazos {
    public static Boolean estaNoPrazo(Date prazo) {
        Date atual = new Date();
        return prazo.after(atual);
    }
}
src/br/usp/ime/academicdevoir/entidade/EstadoDaListaDeRespostas.java
public enum EstadoDaListaDeRespostas {
	SALVA,
	FINALIZADA,
	CORRIGIDA
}
src/br/usp/ime/academicdevoir/infra/UsuarioSession.java
@Component
@SessionScoped
public class UsuarioSession {

	/**
	 * @uml.property  name="usuario"
	 * @uml.associationEnd  
	 */
	private Usuario usuario;

	/**
	 * @return
	 * @uml.property  name="usuario"
	 */
	public Usuario getUsuario() {
		return usuario;
	}

	/**
	 * @param usuario
	 * @uml.property  name="usuario"
	 */
	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public boolean isLogged() {
		return usuario != null;
	}

	public void logout() {
		usuario = null;
	}
}
src/br/usp/ime/academicdevoir/dao/AlunoDao.java
@Component
public class AlunoDao {

	/**
	 * @uml.property  name="session"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final Session session;

	public AlunoDao(Session session) {
		this.session = session;
	}

	/**
	 * Cadastra o aluno fornecido no banco de dados.
	 * 
	 * @param aluno
	 */
	@SuppressWarnings("unchecked")
	public void salvaAluno(Aluno aluno) {
	    String login = aluno.getLogin();
	    List<Usuario> listaDeUsuarios = session.createCriteria(Usuario.class)
                .add(Restrictions.like("login", login, MatchMode.EXACT))
                .list();
        
	    if (listaDeUsuarios.size() != 0) return;
	        
	    Transaction tx = session.beginTransaction();
		session.save(aluno);
		tx.commit();
	}

	/**
	 * Atualiza o aluno fornecido no banco de dados.
	 * 
	 * @param aluno
	 */
	public void atualizaAluno(Aluno aluno) {
		Transaction tx = session.beginTransaction();
		session.update(aluno);
		tx.commit();
	}

	/**
	 * Remove o aluno fornecido do banco de dados.
	 * 
	 * @param aluno
	 */
	public void removeAluno(Aluno aluno) {
		Transaction tx = session.beginTransaction();
		session.delete(aluno);
		tx.commit();
	}

	/**
	 * Devolve um Aluno com o id fornecido.
	 * 
	 * @param id
	 * @return Aluno
	 */
	public Aluno carrega(Long id) {
		return (Aluno) session.load(Aluno.class, id);
	}

	@SuppressWarnings("unchecked")
	/**
	 * Devolve uma lista com todos os alunos cadastrados no banco de dados.
	 * 
	 * @return List<Aluno>
	 */
	public List<Aluno> listaTudo() {
		String nome = "SELECT a FROM Aluno a";
		Query query = session.createQuery(nome);
		List<Aluno> listaDeAlunos = query.list();
		return listaDeAlunos;
	}

	/**
	 * Inscreve o aluno na turma com id fornecido.
	 * 
	 * @param idTurma
	 */
	public void inscreve(Aluno aluno, Turma turma) {
	    Transaction tx = session.beginTransaction();
		aluno.getTurmas().add(turma);
		turma.getAlunos().add(aluno);
		session.update(aluno);
		session.update(turma);
		tx.commit();
	}

	/**
	 * Remove a matricula do aluno na turma especificada
	 * @param aluno
	 * @param turma
	 */
    public void removeMatricula(Aluno aluno, Turma turma) {
        Transaction tx = session.beginTransaction();
        aluno.getTurmas().remove(turma);
        turma.getAlunos().remove(aluno);
        session.update(aluno);
        session.update(turma);
        tx.commit();
    }


}
src/br/usp/ime/academicdevoir/dao/ListaDeExerciciosDao.java
@Component
public class ListaDeExerciciosDao {

	/**
	 * @uml.property name="session"
	 * @uml.associationEnd multiplicity="(1 1)"
	 */
	private final Session session;

	public ListaDeExerciciosDao(Session session) {
		this.session = session;
	}

	@SuppressWarnings("unchecked")
	/**
	 * Devolve uma lista com todas as listas de exercícios cadastradas no banco
	 * de dados.
	 * 
	 * @return List<ListaDeExercicios>
	 */
	public List<ListaDeExercicios> listaTudo() {
		return this.session.createCriteria(ListaDeExercicios.class).list();
	}

	@SuppressWarnings("unchecked")
	/**
	 * Devolve uma lista com todas as listas de exercícios de uma determinada turma.
	 * 
	 * @return List<ListaDeExercicios>
	 */
	public List<ListaDeExercicios> listasDeTurma(Turma turma) {
		List<ListaDeExercicios> listaDeExercicios = this.session
				.createCriteria(ListaDeExercicios.class)
				.add(Restrictions.eq("turma", turma)).list();
		return listaDeExercicios;
	}

	/**
	 * Cadastra a lista fornecida no banco de dados.
	 * 
	 * @param lista
	 */
	public void salva(ListaDeExercicios lista) {
		Transaction tx = session.beginTransaction();
		session.saveOrUpdate(lista);
		tx.commit();
	}

	/**
	 * Devolve uma lista de exercícios com o id fornecido.
	 * 
	 * @param id
	 * @return ListaDeExercicios
	 */
	public ListaDeExercicios carrega(Long id) {
		return (ListaDeExercicios) this.session.load(ListaDeExercicios.class,
				id);
	}

	/**
	 * Atualiza a lista fornecida no banco de dados.
	 * 
	 * @param lista
	 */
	public void atualiza(ListaDeExercicios lista) {
		Transaction tx = session.beginTransaction();
		this.session.update(lista);
		tx.commit();
	}

	/**
	 * Remove a lista fornecida do banco de dados.
	 * 
	 * @param lista
	 */
	public void remove(ListaDeExercicios lista) {
		Transaction tx = session.beginTransaction();
		this.session.delete(lista);
		tx.commit();
	}

	public void recarrega(ListaDeExercicios lista) {
		session.refresh(lista);
	}

	@SuppressWarnings("unchecked")
	public List<BigInteger> buscaListasQueContemQuestao(Long idDaQuestao) {
		return session.createSQLQuery(
				"select ListaDeExercicios_id from questoesDaLista where questao_id="
						+ idDaQuestao).list();
	}
}
src/br/usp/ime/academicdevoir/entidade/Questao.java
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@OnDelete(action = OnDeleteAction.CASCADE)
public abstract class Questao {

	/**
	 * @uml.property  name="id"
	 */
	@Id
	@GeneratedValue
	private Long id;

    @Column(length = Constantes.MAX_TAM_CAMPO)
	protected String enunciado;
	
	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "tags_questoes", joinColumns = { @JoinColumn(name = "id_questao") }, inverseJoinColumns = { @JoinColumn(name = "id_tag") })
	protected List<Tag> tags = new ArrayList<Tag>();

	/**
	 * @return
	 * @uml.property  name="id"
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @param id
	 * @uml.property  name="id"
	 */
	public void setId(Long id) {
		this.id = id;
	}
	
	/**
	 * @return
	 * @uml.property  name="enunciado"
	 */
	public String getEnunciado() {
		return enunciado;
	}

	/**
	 * @param enunciado
	 * @uml.property  name="enunciado"
	 */
	public void setEnunciado(String enunciado) {
		this.enunciado = enunciado;
	}

	public List<Tag> getTags() {
		return tags;
	}
	
	public String getTagsEmString() {
		StringBuffer buffer = new StringBuffer();
		for (Tag tag : this.tags) {
			buffer.append(tag.getNome());
			buffer.append(", ");
		}
		return buffer.toString();
	}

	public void setTags(List<Tag> tags) {
		this.tags = tags;
	}
	
	public void setTags(String stringTags, TagDao dao) {
		if (stringTags == null) return;
		
		List<String> tags = Arrays.asList( stringTags.split(",[ ]*") );
		for (String nome : tags) {
			Tag tag = dao.buscaPeloNome(nome);
			if (tag == null) {
				tag = new Tag(nome);
				dao.salva(tag);
			}
			this.tags.add(tag);
		}		
	}
	
	public abstract TipoDeQuestao getTipo();
	
	public abstract String getRenderizacao();
	
	public abstract String getRenderAlteracao(Resposta resposta);
	
	public String getRenderCorrecao (Resposta resposta) {
        if (resposta == null)
            resposta = new Resposta();
        
        String htmlResult = "";
        StringBuffer buffer = new StringBuffer();

        buffer.append("<p>");
        if (resposta.getValor() != null)
            buffer.append(resposta.getValor());
        buffer.append("</p>");
        buffer.append("<p> Comentários: ");
        if (resposta.getComentario() != null)
            buffer.append(resposta.getComentario());
        buffer.append("</p>");
        buffer.append("<p> Nota: ");
        if (resposta.getNota() != null)
            buffer.append(resposta.getNota());
        buffer.append("</p>");

        htmlResult = buffer.toString();

        return htmlResult;
        
    }
	public abstract Boolean respostaDoAlunoEhCorreta(Resposta respostaAluno);
	
	public abstract Questao copia(TagDao tagDao);
}
src/br/usp/ime/academicdevoir/entidade/ListaDeRespostas.java
@Entity
@SecondaryTable(name = "propriedadesDaListaDeRespostas")
public class ListaDeRespostas {
	
	@Id
	@GeneratedValue
	private Long id;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "id_aluno")
	@Fetch(FetchMode.JOIN)
	@Cascade(CascadeType.SAVE_UPDATE)
	private Aluno aluno;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "id_lista")
	@Fetch(FetchMode.JOIN)
	@Cascade(CascadeType.SAVE_UPDATE)
	private ListaDeExercicios listaDeExercicios;

	@ElementCollection
	@CollectionTable(name = "respostasDaLista")
	private List<Resposta> respostas;
	
	private Double notaFinal;
	
	@Embedded
	private PropriedadesDaListaDeRespostas propriedades;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Aluno getAluno() {
		return aluno;
	}

	public void setAluno(Aluno aluno) {
		this.aluno = aluno;
	}

	public ListaDeExercicios getListaDeExercicios() {
		return listaDeExercicios;
	}

	public void setListaDeExercicios(ListaDeExercicios lista) {
		this.listaDeExercicios = lista;
	}

	public List<Resposta> getRespostas() {
		return respostas;
	}

	public void setRespostas(List<Resposta> respostas) {
		this.respostas = respostas;
	}

	public PropriedadesDaListaDeRespostas getPropriedades() {
		return propriedades;
	}

	public void setPropriedades(PropriedadesDaListaDeRespostas propriedades) {
		this.propriedades = propriedades;
	}

	public Double getNotaFinal() {
		return notaFinal;
	}

	public void setNotaFinal(List<Integer> pesos) {
		Iterator<Resposta> iRespostas = respostas.iterator();
		Iterator<Integer> iPesos = pesos.iterator();
		Double nota;
		Double notaFinal = new Double(0.0);
		Integer peso;
		Integer somaDosPesos = new Integer(0); 
		
		while (iRespostas.hasNext()) {
			nota = iRespostas.next().getNota();
			peso = iPesos.next();
			if (nota != null && peso != null) {
				notaFinal += nota*peso;
				somaDosPesos += peso;
			}
		}
		notaFinal /= somaDosPesos;
		this.notaFinal = notaFinal;
	}

	public int adiciona(Resposta novaResposta) {
		Long id = novaResposta.getQuestao().getId();
		int i = -1;

		for (Resposta resposta : respostas) {
			if (resposta.getQuestao().getId() == id) {
				i = respostas.indexOf(resposta);
				break;
			}
		}
		// FIXME
		if (i < 0) {
		    if (novaResposta.getValor() != null && 
                    !novaResposta.getValor().isEmpty())
		    respostas.add(novaResposta);
		}
		else respostas.set(i, novaResposta);
		return i;
	}
	
	public void autocorrecao() {
	    //List para os pesos das questões usados na nota final
	    List<Integer> pesosDasQuestoes = new ArrayList<Integer>();
	    QuestaoDaLista questaoDaLista = null;
	    
	    //Para cada resposta dessa lista
	    for (Resposta resposta : respostas) {
        
            //Pegando a questao a qual a resposta se refere
            Questao questao = resposta.getQuestao();
        
            //Obtendo a Questao relacionada com a lista para obter as propriedades
            //QuestaoDaLista questaoDaLista = questaoDaListaDao.getQuestaoDaListaPorIds(id, questao.getId());
        
            for (QuestaoDaLista i : listaDeExercicios.getQuestoes())
                if (i.getQuestao().equals(questao)) {
                questaoDaLista = i;
                break;
            }
            //Montando o vetor de pesos para o cálculo da nota final
            pesosDasQuestoes.add(questaoDaLista.getPeso());
        
            //Resultado da Comparação da Resposta (Correção): True se correta, False se errada e NULL se aberta. 
            Boolean resultado = questao.respostaDoAlunoEhCorreta(resposta);
        
            if (resultado != null)
            //Verificando se a resposta está certa ou não.
                if(resultado == true) resposta.setNota(100.0);
            //#TODO Questões abertas?? Como faz??
            //else if (resultado == false) resposta.setNota(0.0);  Abaixo seria o NULL
                else resposta.setNota(0.0);
	    }
    
	    //Atribuindo a nota final à lista
	    setNotaFinal(pesosDasQuestoes);
	
	}
}
src/br/usp/ime/academicdevoir/dao/DisciplinaDao.java
@Component
public class DisciplinaDao {

	/**
	 * @uml.property  name="session"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private final Session session;
	
	public DisciplinaDao(Session session) {
		this.session = session;
	}

	/**
	 * Cadastra a disciplina fornecida no banco de dados.
	 * 
	 * @param disciplina
	 */
	@SuppressWarnings("unchecked")
	public void salvaDisciplina(Disciplina disciplina) {
		String nome = disciplina.getNome();
	    List<Disciplina> listaDeDisciplinas = session.createCriteria(Disciplina.class)
                .add(Restrictions.like("nome", nome, MatchMode.EXACT))
                .list();
        
	    if (listaDeDisciplinas.size() != 0) return;
	    
		Transaction tx = session.beginTransaction();
		session.save(disciplina);
		tx.commit();
	}

	/**
	 * Atualiza a disciplina fornecida no banco de dados. 
	 * 
	 * @param disciplina
	 */
	@SuppressWarnings("unchecked")
	public void atualizaDisciplina(Disciplina disciplina) {
		String nome = disciplina.getNome();
	    List<Disciplina> listaDeDisciplinas = session.createCriteria(Disciplina.class)
                .add(Restrictions.like("nome", nome, MatchMode.EXACT))
                .list();
        
	    if (listaDeDisciplinas.size() != 0 && listaDeDisciplinas.get(0).getId() != disciplina.getId()) return;
	    
		Transaction tx = session.beginTransaction();
		session.update(disciplina);
		tx.commit();
	}
	
	/**
	 * Remove a disciplina fornecida do banco de dados.
	 * 
	 * @param disciplina
	 */
	public void removeDisciplina(Disciplina disciplina) {
		try{
			Transaction tx = session.beginTransaction();
			session.delete(disciplina);
			tx.commit();
		} catch (Exception e) { 
    		return; /*Não foi possível remover a disciplina, pois tem alguma turma associada.*/
    	}
	}
	
	/**
	 * Devolve uma disciplina com o id fornecido.
	 * 
	 * @param id
	 * @return Disciplina
	 */
	public Disciplina carrega(Long id) {
		return (Disciplina) session.load(Disciplina.class, id);
	}
	
    @SuppressWarnings("unchecked")
    /**
	 * Devolve uma lista com todas as disciplinas cadastradas no banco de dados.
	 * 
	 * @return List<Disciplina>
	 */
   /* public List<Disciplina> listaTudo() {
		String nome = "SELECT p FROM Disciplina p";
		Query query = session.createQuery(nome);
		List<Disciplina> listaDeDisciplinas = query.list();
		return listaDeDisciplinas;
	}*/
    
    public List<Disciplina> listaTudo() {
		return this.session.createCriteria(Disciplina.class).list();
	}

}


Question: package br.usp.ime.academicdevoir.controller;
import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.interceptor.multipart.UploadedFile;
import br.usp.ime.academicdevoir.arquivos.Arquivos;
import br.usp.ime.academicdevoir.dao.AlunoDao;
import br.usp.ime.academicdevoir.dao.DisciplinaDao;
import br.usp.ime.academicdevoir.dao.ListaDeExerciciosDao;
import br.usp.ime.academicdevoir.dao.ListaDeRespostasDao;
import br.usp.ime.academicdevoir.dao.QuestaoDao;
import br.usp.ime.academicdevoir.entidade.EstadoDaListaDeRespostas;
import br.usp.ime.academicdevoir.entidade.ListaDeRespostas;
import br.usp.ime.academicdevoir.entidade.Questao;
import br.usp.ime.academicdevoir.entidade.Resposta;
import br.usp.ime.academicdevoir.infra.TipoDeQuestao;
import br.usp.ime.academicdevoir.infra.UsuarioSession;
import br.usp.ime.academicdevoir.infra.VerificadorDePrazos;


@Resource
public class RespostasController {

	private final ListaDeRespostasDao dao;
	//private final ListaDeExerciciosDao listaDeExerciciosDao;
	//private final AlunoDao alunoDao;
	//private final DisciplinaDao disciplinaDao;
	//private final UsuarioSession usuario;
	private final Arquivos arquivos;
	private final Result result;
	//private final Validator validator;
	private final QuestaoDao questaoDao;

	public RespostasController(ListaDeRespostasDao dao,
			ListaDeExerciciosDao listaDeExerciciosDao, AlunoDao alunoDao, DisciplinaDao disciplinaDao,
			UsuarioSession usuario, Arquivos arquivos, Result result, Validator validator, QuestaoDao questaoDao) {
		this.dao = dao;
		//this.listaDeExerciciosDao = listaDeExerciciosDao;
		//this.alunoDao = alunoDao;
		//this.disciplinaDao = disciplinaDao;
		this.questaoDao = questaoDao;
		//this.usuario = usuario;
		this.arquivos = arquivos;
		this.result = result;
		//this.validator = validator;
	}
	
	/**
	 * Salva uma resposta referente na lista de respostas fornecida.
	 * @param listaDeRespostas
	 * @param listaDeExercicios
	 */
	@Post
	@Path("/respostas/{listaDeRespostas.id}/cadastra")
	public void salvaResposta(ListaDeRespostas listaDeRespostas, Resposta resposta, Long idDaQuestao, UploadedFile arquivo) {
	    String caminho;
	    int nenvios, nmaxenvios;
	    if (resposta == null) resposta = new Resposta();
		
	    dao.recarrega(listaDeRespostas);
	    
	    
        if (listaDeRespostas.getPropriedades().getEstado() == 
                EstadoDaListaDeRespostas.SALVA && 
Answer:                 !VerificadorDePrazos.estaNoPrazo(listaDeRespostas.