@Entity
public class ConfiguracaoPagina extends Identity<Integer> {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_config_pagina")
    @SequenceGenerator(name = "seq_config_pagina", sequenceName = "seq_config_pagina", allocationSize = 1, initialValue = 1)
    private Integer             id;

    @ManyToOne
    private MaterialConfigurado materialConfigurado;

    private Integer             pagina;

    private Integer             minMinutosPorPagina;

    @ManyToMany(cascade = CascadeType.ALL)
    @CollectionTable(name = "CONFIGURACAOPAGINAQUESTAO")
    @OrderBy("id")
    private List<Questao>       questoes;

    public Integer getId() {
        return id;
    }

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

    public MaterialConfigurado getMaterialConfigurado() {
        return materialConfigurado;
    }

    public void setMaterialConfigurado(MaterialConfigurado materialConfigurado) {
        this.materialConfigurado = materialConfigurado;
    }

    public Integer getPagina() {
        return pagina;
    }

    public void setPagina(Integer pagina) {
        this.pagina = pagina;
    }

    public Integer getMinMinutosPorPagina() {
        return minMinutosPorPagina;
    }

    public void setMinMinutosPorPagina(Integer minMinutosPorPagina) {
        this.minMinutosPorPagina = minMinutosPorPagina;
    }

    public List<Questao> getQuestoes() {
        return questoes;
    }

    public void setQuestoes(List<Questao> questoes) {
        this.questoes = questoes;
    }

} @Entity
public class Material extends DominioProfessor<Integer> {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_material")
    @SequenceGenerator(name = "seq_material", sequenceName = "seq_material", allocationSize = 1, initialValue = 1)
    private Integer              id;

    @Column(length = 50)
    private String               titulo;

    @Column(length = 50)
    private String               arquivoUnico;

    private Integer              numeroPaginas;

    @ElementCollection
    @MapKeyColumn(name = "pagina")
    @Column(name = "arquivoPaginado", length = 50)
    @CollectionTable(name = "MATERIALPAGINADO")
    private Map<Integer, String> arquivoPaginado;

    public Integer getId() {
        return id;
    }

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

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public Integer getNumeroPaginas() {
        return numeroPaginas;
    }

    public void setNumeroPaginas(Integer numeroPaginas) {
        this.numeroPaginas = numeroPaginas;
    }

    public String getArquivoUnico() {
        return arquivoUnico;
    }

    public void setArquivoUnico(String arquivoUnico) {
        this.arquivoUnico = arquivoUnico;
    }

    public Map<Integer, String> getArquivoPaginado() {
        return arquivoPaginado;
    }

    public void setArquivoPaginado(Map<Integer, String> arquivoPaginado) {
        this.arquivoPaginado = arquivoPaginado;
    }

} @Entity
public class MaterialConfigurado extends DominioProfessor<Integer> {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_mat_configurado")
    @SequenceGenerator(name = "seq_mat_configurado", sequenceName = "seq_mat_configurado", allocationSize = 1, initialValue = 1)
    private Integer                          id;

    @ManyToOne
    private Material                         material;

    private Integer                          minMinutosPorPagina;

    @MapKey(name = "pagina")
    @OrderBy("pagina")
    @OneToMany(mappedBy = "materialConfigurado", cascade = CascadeType.ALL)
    private Map<Integer, ConfiguracaoPagina> configuracaoPaginas;

    public Integer getId() {
        return id;
    }

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

    public Material getMaterial() {
        return material;
    }

    public void setMaterial(Material material) {
        this.material = material;
    }

    public Integer getMinMinutosPorPagina() {
        return minMinutosPorPagina;
    }

    public void setMinMinutosPorPagina(Integer minMinutosPorPagina) {
        this.minMinutosPorPagina = minMinutosPorPagina;
    }

    public Map<Integer, ConfiguracaoPagina> getConfiguracaoPaginas() {
        return configuracaoPaginas;
    }

    public void setConfiguracaoPaginas(Map<Integer, ConfiguracaoPagina> configuracaoPaginas) {
        this.configuracaoPaginas = configuracaoPaginas;
    }

} @Entity
@DiscriminatorValue("PROFESSOR")
public class Professor extends Aluno {

} @Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "TIPO", length = 50)
public abstract class Questao extends Identity<Integer> {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_questao")
    @SequenceGenerator(name = "seq_questao", sequenceName = "seq_questao", allocationSize = 1, initialValue = 1)
    private Integer      id;

    @Column(length = 1000)
    private String       descricao;

    private Integer      peso;

    @ElementCollection
    @CollectionTable(name = "QUESTAOHABILIDADE")
    @Column(name = "habilidade", length = 50)
    private List<String> habilidades;

    public Integer getId() {
        return id;
    }

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

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public List<String> getHabilidades() {
        return habilidades;
    }

    public void setHabilidades(List<String> habilidades) {
        this.habilidades = habilidades;
    }

    public Integer getPeso() {
        return peso;
    }

    public void setPeso(Integer peso) {
        this.peso = peso;
    }

} @Entity
@DiscriminatorValue("DISSERTATIVA")
public class QuestaoDissertativa extends Questao {

} public class ConfigurarMaterialModel {

    @NotNull
    private Integer                     idMaterialConfiguracao;

    @Valid
    private List<ConfigurarPaginaModel> paginas;

    public List<ConfigurarPaginaModel> getPaginas() {
        return paginas;
    }

    public void setPaginas(List<ConfigurarPaginaModel> paginas) {
        this.paginas = paginas;
    }

    public Integer getIdMaterialConfiguracao() {
        return idMaterialConfiguracao;
    }

    public void setIdMaterialConfiguracao(Integer idMaterialConfiguracao) {
        this.idMaterialConfiguracao = idMaterialConfiguracao;
    }

} public class ConfigurarPaginaModel {

    @NotNull
    private Integer      tempo;
    private List<String> questoes;
    private String       url;

    public Integer getTempo() {
        return tempo;
    }

    public void setTempo(Integer tempo) {
        this.tempo = tempo;
    }

    public List<String> getQuestoes() {
        return questoes;
    }

    public void setQuestoes(List<String> questoes) {
        this.questoes = questoes;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

} public class CriarMaterialModel {

    @NotEmpty(message = "O arquivo é obrigatório e não foi carregado")
    @Pattern(regexp = "(.+\\.pdf)?", message = "Apenas arquivos do tipo PDF são aceitos")
    private String  nomeArquivo;

    @NotEmpty
    @Size(max = 50)
    private String  titulo;

    @NotNull
    @Max(99)
    private Integer minutos;

    public String getNomeArquivo() {
        return nomeArquivo;
    }

    public void setNomeArquivo(String nomeArquivo) {
        this.nomeArquivo = nomeArquivo;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public Integer getMinutos() {
        return minutos;
    }

    public void setMinutos(Integer minutos) {
        this.minutos = minutos;
    }

} public interface ConfiguracaoPaginaRepository extends EntityRepository<ConfiguracaoPagina, Integer> {

} public interface DocumentosRepository {

    Map<Integer, String> dividirArquivo(String nomeArquivo);

    Map<Integer, String> dividirPdf(InputStream inputStream);

} public interface MaterialConfiguradoRepository extends EntityRepository<MaterialConfigurado, Integer> {

    MaterialConfigurado findByIdAndProfessor(Integer id, Professor professor);

} public interface MaterialRepository extends EntityRepository<Material, Integer> {

	List<Material> findByProfessor(Professor professor);
	
} public interface QuestaoRepository extends EntityRepository<Questao, Integer> {

} public interface MaterialService {

    Result<MaterialConfigurado> criarMaterial(CriarMaterialModel material, Professor professor);

    Result<MaterialConfigurado> talvezAlterarMaterial(CriarMaterialModel material, Professor professorAutenticado);

    CriarMaterialModel buscarMaterial(Integer idMatConfigurado, Professor professorAutenticado);

    ConfigurarMaterialModel buscarConfiguracaoMaterial(Integer idMatConfigurado, Professor professor);

    Result<Void> configurarMaterial(ConfigurarMaterialModel configuracao, Professor professor);

	Result<MaterialConfigurado> reusarMaterial(Integer materialId, Professor professor, Integer minutosPadrao);

	List<Material> buscarMaterialParaReuso(Professor professorAutenticado);

} public class Result<E> {

    public enum Status {
        SUCCESS, FAILURE
    }

    private final String    message;
    private final Status    status;
    private final E         value;
    private final Violation violation;

    private Result(String message, E value) {
        this.message = message;
        this.status = Status.SUCCESS;
        this.value = value;
        this.violation = null;
    }

    private Result(Violation violation, E value) {
        this.message = violation.getMessage();
        this.status = Status.FAILURE;
        this.value = value;
        this.violation = violation;
    }

    public static final <E> Result<E> success(String message) {
        return new Result<E>(message, null);
    }

    public static final <E> Result<E> success(String message, E value) {
        return new Result<E>(message, value);
    }

    public static final <E> Result<E> failure(Violation violation) {
        return new Result<E>(violation, null);
    }

    public static final <E> Result<E> failure(Violation violation, E value) {
        return new Result<E>(violation, value);
    }

    public String getMessage() {
        return message;
    }

    public boolean isSuccess() {
        return status == Status.SUCCESS;
    }

    public boolean isFailure() {
        return status == Status.FAILURE;
    }

    public boolean hasValue() {
        return Has.content(value);
    }

    public E getValue() {
        return value;
    }

    public Violation getViolation() {
        return violation;
    }

    public Status getStatus() {
        return status;
    }

    public boolean failsAt(Violation violation, Violation... violations) {
        if (this.violation == null || this.status == Status.SUCCESS) {
            return false;
        }

        if (this.violation == violation || violation.equals(this.violation)) {
            return true;
        }

        if (violations != null && violations.length > 0) {
            for (Violation v : violations) {
                if (this.violation == v || this.violation.equals(v)) {
                    return true;
                }
            }
        }

        return false;
    }

}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import javax.inject.Named;
import org.springframework.transaction.annotation.Transactional;
import br.com.delogic.leitoor.entidade.ConfiguracaoPagina;
import br.com.delogic.leitoor.entidade.Material;
import br.com.delogic.leitoor.entidade.MaterialConfigurado;
import br.com.delogic.leitoor.entidade.Professor;
import br.com.delogic.leitoor.entidade.Questao;
import br.com.delogic.leitoor.entidade.QuestaoDissertativa;
import br.com.delogic.leitoor.model.ConfigurarMaterialModel;
import br.com.delogic.leitoor.model.ConfigurarPaginaModel;
import br.com.delogic.leitoor.model.CriarMaterialModel;
import br.com.delogic.leitoor.repository.ConfiguracaoPaginaRepository;
import br.com.delogic.leitoor.repository.DocumentosRepository;
import br.com.delogic.leitoor.repository.MaterialConfiguradoRepository;
import br.com.delogic.leitoor.repository.MaterialRepository;
import br.com.delogic.leitoor.repository.QuestaoRepository;
import br.com.delogic.leitoor.service.MaterialService;
import br.com.delogic.leitoor.util.Result;
package br.com.delogic.leitoor.service.impl;





@Named("materialService")
public class MaterialServiceImpl implements MaterialService {

    @Inject
    private MaterialRepository            materialRepository;

    @Inject
    private DocumentosRepository          documentoRepository;

    @Inject
    private MaterialConfiguradoRepository matConfiguradoRepository;