Subversion Repositories bacoAlunos

Rev

Rev 1380 | Rev 1394 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package pt.estgp.estgweb.services.questionarios.pedagogico;

import com.owlike.genson.TransformationException;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import pt.estgp.estgweb.domain.*;
import pt.estgp.estgweb.domain.dao.DaoFactory;
import pt.estgp.estgweb.domain.dao.impl.CourseUnitDaoImpl;
import pt.estgp.estgweb.services.jobs.JobDeamon;
import pt.estgp.estgweb.services.jobs.ServiceJob;
import pt.estgp.estgweb.services.logresults.ILogMessages;
import pt.estgp.estgweb.services.logresults.LogMessageTypeEnum;
import pt.estgp.estgweb.services.logresults.impl.DefaultLogMessage;
import pt.estgp.estgweb.services.logresults.impl.DefaultLogMessages;
import pt.estgp.estgweb.services.questionarios.QuestionariosService;
import pt.estgp.estgweb.utils.ConfigProperties;
import pt.estgp.estgweb.web.exceptions.NotAuthorizedException;
import pt.utl.ist.berserk.logic.serviceManager.IService;

import java.io.IOException;
import java.util.*;


/**
 * Created by jorgemachado on 22/03/16.
 */

public class UpdateCoursesAndUnitsJobService extends ServiceJob implements IService
{

    public static final 1.5.0/docs/api/java/util/logging/Logger.html">Logger logger = 1.5.0/docs/api/java/util/logging/Logger.html">Logger.getLogger(UpdateCoursesAndUnitsJobService.class);

    //return similar questionarios in same year, semestre and history category
    public List<QuestionarioImpl> setAnoSemestre(1.5.0/docs/api/java/lang/String.html">String year, 1.5.0/docs/api/java/lang/String.html">String semestre, long questionarioId, UserSession userSession,QuestionarioImpl questionarioCleared) throws NotAuthorizedException
    {
        if(questionarioCleared.isClear((UserSessionImpl) userSession,QuestionarioImpl.QuestionarioClearancesOperation.QUESTIONARIO_SET_ANO_SEMESTRE.name()))
        {
            questionarioCleared.setYear(year);
            questionarioCleared.setSemestre(semestre);
            questionarioCleared.setSubStatePedagogicoClass(QuestionarioImpl.SubStatePedagogico.YEAR_SEMESTRE_ASSIGNED);
            List<QuestionarioImpl> similar = DaoFactory.getQuestionarioDaoImpl().findAnoSemestre(year, semestre, questionarioCleared.getQuestionarioHistoryDrive().getId());
            new QuestionariosService().loadInit(similar);
            return similar;
        }
        else
            throw new NotAuthorizedException("Não pode alterar o formulário porque o questionário está num estado avançado");
    }


    public 1.5.0/docs/api/java/lang/String.html">String[] deserializeCoursesList(QuestionarioImpl questionario)
    {
        JobServiceTaskImpl job = questionario.getCourseSelectionTaskId() > 0 ?
                (JobServiceTaskImpl) DaoFactory.getJobServiceTaskDaoImpl().load(questionario.getCourseSelectionTaskId()) :
                null;
        if(job == null)
            return new 1.5.0/docs/api/java/lang/String.html">String[0];

        1.5.0/docs/api/java/lang/String.html">String courses = job.getParameter(ServiceJob.JOB_questionario_courseList_KEY).getObject();
        return deserializeCoursesList(courses);
    }

    public List<Course> getCoursesList(1.5.0/docs/api/java/lang/String.html">String coursesListJson)
    {
        List<Course> courses = new ArrayList<Course>();
        1.5.0/docs/api/java/lang/String.html">String[] courseIds = deserializeCoursesList(coursesListJson);
        for(1.5.0/docs/api/java/lang/String.html">String courseId: courseIds)
        {
            try
            {
                Course c = DaoFactory.getCourseDaoImpl().load(new 1.5.0/docs/api/java/lang/Long.html">Long(courseId));
                courses.add(c);
            }
            catch(1.5.0/docs/api/java/lang/Throwable.html">Throwable e)
            {
                logger.info("Course not found in course list with id:" + courseId);
            }
        }
        return courses;
    }

    public 1.5.0/docs/api/java/lang/String.html">String[] deserializeCoursesList(1.5.0/docs/api/java/lang/String.html">String json)
    {
        try {

            JSONArray jsonArray = new JSONArray(json);
            1.5.0/docs/api/java/lang/String.html">String[] coursesList = new 1.5.0/docs/api/java/lang/String.html">String[jsonArray.length()];
            for(int i=0;i <jsonArray.length();i++)
            {
                coursesList[i] = ""+ jsonArray.get(i);
            }
            return coursesList;
        } catch (JSONException e) {
            logger.error(e,e);
        }
        return new 1.5.0/docs/api/java/lang/String.html">String[0];
    }

    public QuestionarioImpl runJobSelectCourses(long questionarioId,1.5.0/docs/api/java/lang/String.html">String[] coursesList,UserSession session,QuestionarioImpl questionarioCleared) throws NotAuthorizedException {

        if(!questionarioCleared.isClear((UserSessionImpl) session,QuestionarioImpl.QuestionarioClearancesOperation.QUESTIONARIO_SCHEDULLE_SELECT_COURSES.name()))
        {
            throw new NotAuthorizedException("Nao tem autorização para agendar atribuições de cursos");
        }
        ( questionarioCleared).setSubStatePedagogicoClass(QuestionarioImpl.SubStatePedagogico.ASSIGNING_COURSES);
        JSONArray jsonArray = new JSONArray();
        for(1.5.0/docs/api/java/lang/String.html">String sele: coursesList)
        {
            jsonArray.put(new 1.5.0/docs/api/java/lang/Long.html">Long(sele));
        }

        Set<JobServiceTaskParameter> paramsJob = new HashSet<JobServiceTaskParameter>();

        JobServiceTaskParameterImpl paramJobL = DomainObjectFactory.createJobServiceTaskParameterImpl();
        paramJobL.setName(ServiceJob.JOB_questionario_courseList_KEY);
        paramJobL.setDescription("lista de cursos a associar");
        paramJobL.setObject(jsonArray.toString());
        paramsJob.add(paramJobL);


        JobServiceTaskParameterImpl paramJob = DomainObjectFactory.createJobServiceTaskParameterImpl();
        paramJob.setName(ServiceJob.JOB_questionario_id_KEY);
        paramJob.setDescription("ID do questionário");
        paramJob.setObject("" + questionarioId);
        paramsJob.add(paramJob);

        JobServiceTask job = JobDeamon.createServiceJob(UpdateCoursesAndUnitsJobService.class, session.getUser(), paramsJob,
                "Service: Atribuição de Cursos e Unidades a um questionário Pedagógico");
        questionarioCleared.setCourseSelectionTaskId(job.getId());
        return questionarioCleared;
    }


    /**
     *
     * @param questionarioId
     * @param session
     * @param questionarioCleared
     * @throws NotAuthorizedException
     *
     */

    public ILogMessages revertAllAssignments(long questionarioId, UserSession session,QuestionarioImpl questionarioCleared) throws NotAuthorizedException {

        DefaultLogMessages logMessages = new DefaultLogMessages();
        if(!questionarioCleared.isClear((UserSessionImpl) session,QuestionarioImpl.QuestionarioClearancesOperation.QUESTIONARIO_REVERT_ALL_ASSIGNEMENTS.name()))
        {
            throw new NotAuthorizedException("Nao tem autorização para agendar atribuições de cursos");
        }
        for(QuestionarioPedagogicoCursoAfeto cu : DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().find(questionarioId))
        {
            int unidades = 0;
            if(cu.getUnidadesAfetas() != null)
            {
                unidades = cu.getUnidadesAfetas().size();
                for(QuestionarioPedagogicoUnidadeCurricularAfeta unidadeCurricularAfeta: cu.getUnidadesAfetas())
                {
                    logger.info("Reverting Unidade Curricular Afeta " + unidadeCurricularAfeta.getCodigoUnidade() + " - " + unidadeCurricularAfeta.getNome());
                    unidadeCurricularAfeta.setCursoAfeto(null);
                    DaoFactory.getQuestionarioPedagogicoUnidadeCurricularAfetaDaoImpl().delete(unidadeCurricularAfeta);
                    if(unidadeCurricularAfeta.getTipologiasRequisitadas() != null && unidadeCurricularAfeta.getTipologiasRequisitadas().size() > 0)
                    {
                        1.5.0/docs/api/java/lang/String.html">String msg = "A unidade " + unidadeCurricularAfeta.getCodigoUnidade() + " tem tipologias requisitadas que tem de ser removidas primeiro, iremos remover todas as tipologias e respostas candidatas associadas";
                        logger.warn(msg);
                        logMessages.addMessage(new DefaultLogMessage("questionario.courses.selection", LogMessageTypeEnum.WARNING,msg));
                        removeTipologiasERespostasCascade(unidadeCurricularAfeta);
                    }
                }
            }
            1.5.0/docs/api/java/lang/String.html">String msg = "Removendo curso afeto:" + cu.getNome() + " e " + unidades + " uniades afetas";
            logger.info(msg);
            logMessages.addMessage(new DefaultLogMessage("questionario.courses.selection", LogMessageTypeEnum.INFO,msg));

            cu.setUnidadesAfetas(null);
            DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().delete(cu);
        }
        questionarioCleared.setSubStatePedagogicoClass(QuestionarioImpl.SubStatePedagogico.YEAR_SEMESTRE_ASSIGNED);
        return logMessages;
    }


    public ILogMessages revertAllRespostasCandidatas(long questionarioId) throws NotAuthorizedException {

        DefaultLogMessages logMessages = new DefaultLogMessages();
        1.5.0/docs/api/java/lang/String.html">String msg = "Revertendo respostas candidatas do questionario " + questionarioId;
        logger.warn(msg);
        serviceLogWarn(msg);

        for(QuestionarioPedagogicoCursoAfeto cu : DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().find(questionarioId))
        {
            msg = "Revertendo respostas do curso " + cu.getCodigoCurso() + " , iremos remover todas as tipologias e respostas candidatas associadas";
            logger.warn(msg);
            serviceLogWarn(msg);

            int unidades = 0;
            if(cu.getUnidadesAfetas() != null)
            {
                unidades = cu.getUnidadesAfetas().size();
                for(QuestionarioPedagogicoUnidadeCurricularAfeta unidadeCurricularAfeta: cu.getUnidadesAfetas())
                {
                    logger.info("Reverting Respostas Unidade Curricular Afeta " + unidadeCurricularAfeta.getCodigoUnidade() + " - " + unidadeCurricularAfeta.getNome());
                    if(unidadeCurricularAfeta.getTipologiasRequisitadas() != null && unidadeCurricularAfeta.getTipologiasRequisitadas().size() > 0)
                    {
                        msg = "A unidade " + unidadeCurricularAfeta.getCodigoUnidade() + " tem tipologias requisitadas que tem de ser removidas primeiro, iremos remover todas as tipologias e respostas candidatas associadas";
                        logger.warn(msg);
                        serviceLogWarn(msg);
                        logMessages.addMessage(new DefaultLogMessage("questionario.courses.selection", LogMessageTypeEnum.WARNING,msg));
                        removeTipologiasERespostasCascade(unidadeCurricularAfeta);
                    }
                }
            }
            msg = "Removendo curso afeto:" + cu.getNome() + " e " + unidades + " uniades afetas";
            logger.info(msg);
            serviceLogWarn(msg);
            logMessages.addMessage(new DefaultLogMessage("questionario.courses.selection", LogMessageTypeEnum.INFO,msg));
        }
        return logMessages;
    }

    /**
     *
     */

    protected void removeTipologiasERespostasCascade(QuestionarioPedagogicoUnidadeCurricularAfeta unidadeAfeta)
    {
        for(QuestionarioPedagogicoTipologiaRequisitada tr: unidadeAfeta.getTipologiasRequisitadas())
        {
            logger.warn("deleting: " + tr);
            if(tr.getAlunosRequisitados() != null)
            {
                for(QuestionarioPedagogicoAlunoRequisitado ar: tr.getAlunosRequisitados())
                {
                    logger.warn("deleting: " + ar);
                    if(ar.getRespostaRequisitada() != null)
                    {
                        logger.warn("deleting: Resposta Requisitada " + ar.getRespostaRequisitada().getId());
                        if(ar.getRespostaRequisitada().getResposta() != null)
                        {
                            logger.warn("deleting resposta: " + ar.getRespostaRequisitada().getResposta());
                            DaoFactory.getQuestionarioRespostaDaoImpl().delete(ar.getRespostaRequisitada().getResposta());
                            ar.getRespostaRequisitada().setResposta(null);
                        }
                        DaoFactory.getQuestionarioRespostaRequisitadaDaoImplImpl().delete(ar.getRespostaRequisitada());
                        ar.setRespostaRequisitada(null);
                    }
                    DaoFactory.getQuestionarioPedagogicoAlunoRequisitadoDaoImpl().delete(ar);
                }
                tr.setAlunosRequisitados(null);
            }
            DaoFactory.getQuestionarioPedagogicoTipologiaRequisitadaDaoImpl().delete(tr);
        }
        unidadeAfeta.setTipologiasRequisitadas(null);
    }

    /**
     *
     * @return
     * @throws Throwable
     */

    @1.5.0/docs/api/java/lang/Override.html">Override
    protected ILogMessages runJobServiceTask() throws 1.5.0/docs/api/java/lang/Throwable.html">Throwable
    {

        DefaultLogMessages logMessages = new DefaultLogMessages();
        long questionarioId = 1.5.0/docs/api/java/lang/Long.html">Long.parseLong(getParametersMap().get(ServiceJob.JOB_questionario_id_KEY).getObject());
        QuestionarioImpl q = (QuestionarioImpl) DaoFactory.getQuestionarioDaoImpl().load(questionarioId);

        1.5.0/docs/api/java/lang/String.html">String[] coursesList = deserializeCoursesList(q);
        //Colocamos já aqui o estado para nao se poder mudar o Ano e o Semestre

        /**logging**/
        1.5.0/docs/api/java/lang/String.html">String msg = "Starting running service for questionario: " + q.getId() + " - " + q.getiAnswersProcessorClass().getTitle();
        serviceLogInfo(msg);
        logger.info(msg);
        /**logging**/

        revertAllRespostasCandidatas(questionarioId);

        List<String> newCourseCodesList = new ArrayList<String>();
        int count = 0;
        int totalCourses = coursesList.length;
        for(1.5.0/docs/api/java/lang/String.html">String courseStrId: coursesList)
        {
            count++;
            try{
                1.5.0/docs/api/java/lang/Long.html">Long courseLong = 1.5.0/docs/api/java/lang/Long.html">Long.parseLong(courseStrId);
                /** logging **/
                msg = "Loading Course BACO ID: " + courseStrId;
                serviceLogInfo(msg);
                logger.info(msg);
                /** logging **/

                Course c = DaoFactory.getCourseDaoImpl().load(courseLong);
                newCourseCodesList.add(c.getCode());
                /** logging **/
                msg = "(" + count + " of " + totalCourses + ")-> Course loaded: " + c.getName() + "(" + c.getCode() + ")";
                serviceLogInfo(msg);
                logger.info(msg);
                /** logging **/

                createCursoAfeto(q, c, logMessages);

                /** COMMIT OPERATION **/
                setProgress((int)((((float)count)/((float)totalCourses))*100.0f));
                commitPartially();
                DaoFactory.getQuestionarioDaoImpl().update(q);
                /** COMMIT OPERATION **/
            }
            catch(1.5.0/docs/api/java/lang/Throwable.html">Throwable t)
            {
                logger.error(t,t);
                serviceLogError(t.toString(),t);
                logMessages.addMessage(new DefaultLogMessage("questionario.courses.selection", LogMessageTypeEnum.ERROR,t.toString()));
            }

        }

        removeUnselectedCourses(q, newCourseCodesList);

        /** COMMIT OPERATION **/
        setProgress(100);
        commitPartially();
        DaoFactory.getQuestionarioDaoImpl().update(q);
        /** COMMIT OPERATION **/


        msg = "Set courses state as " + QuestionarioImpl.SubStatePedagogico.COURSES_ASSIGNED.name();
        serviceLogInfo(msg);
        logger.info(msg);
        q.setSubStatePedagogicoClass(QuestionarioImpl.SubStatePedagogico.COURSES_ASSIGNED);
        commitPartially();

        return logMessages;
    }

    /**
     *
     * @param q
     * @param newCourseCodesList
     */

    private void removeUnselectedCourses(QuestionarioImpl q, List<String> newCourseCodesList) {
        /** logging **/
        1.5.0/docs/api/java/lang/String.html">String msg = "Removing unselected courses ";
        serviceLogInfo(msg);
        logger.info(msg);
        /** logging **/
        List<QuestionarioPedagogicoCursoAfeto> allCoursesInQuestionario =  DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().find(q.getId());
        for(QuestionarioPedagogicoCursoAfeto cursoAfeto: allCoursesInQuestionario)
        {
            if(!newCourseCodesList.contains(cursoAfeto.getCodigoCurso()))
            {
                removeCursoAfeto(cursoAfeto);
            }
        }
    }

    private void removeCursoAfeto(QuestionarioPedagogicoCursoAfeto cursoAfeto) {
        1.5.0/docs/api/java/lang/String.html">String msg; /** logging **/
        msg = "Deleting course: " + cursoAfeto.getCodigoCurso();
        serviceLogInfo(msg);
        logger.info(msg);
        /** logging **/
        for(QuestionarioPedagogicoUnidadeCurricularAfeta unidade: cursoAfeto.getUnidadesAfetas())
        {
            /** logging **/
            msg = "--->Deleting unit from course: " + unidade.getCodigoUnidade();
            serviceLogInfo(msg);
            logger.info(msg);
            /** logging **/
            DaoFactory.getQuestionarioPedagogicoUnidadeCurricularAfetaDaoImpl().delete(unidade);
        }
        cursoAfeto.setUnidadesAfetas(null);
        DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().delete(cursoAfeto);
    }

    private void removeUnselectedUnits(QuestionarioPedagogicoCursoAfeto cursoAfetado, List<String> newUnidadesCodesList) {
        /** logging **/
        1.5.0/docs/api/java/lang/String.html">String msg = "Removing unselected units from course: " + cursoAfetado.getCodigoCurso();
        serviceLogInfo(msg);
        logger.info(msg);
        /** logging **/
        Set<QuestionarioPedagogicoUnidadeCurricularAfeta> allUnidades =  cursoAfetado.getUnidadesAfetas();
        for(QuestionarioPedagogicoUnidadeCurricularAfeta unidadeAfeta: allUnidades)
        {
            if(!newUnidadesCodesList.contains(unidadeAfeta.getCodigoUnidade()))
            {
                /** logging **/
                msg = "--->Deleting unidade: " + unidadeAfeta.getCodigoUnidade();
                serviceLogInfo(msg);
                logger.info(msg);
                /** logging **/
                DaoFactory.getQuestionarioPedagogicoUnidadeCurricularAfetaDaoImpl().delete(unidadeAfeta);
            }
        }
    }


    /**
     *
     * @param q
     * @param c
     * @throws IOException
     * @throws TransformationException
     */

    private void createCursoAfeto(QuestionarioImpl q, Course c, DefaultLogMessages logMessages) throws 1.5.0/docs/api/java/io/IOException.html">IOException, TransformationException
    {
        1.5.0/docs/api/java/lang/String.html">String msg;
        QuestionarioPedagogicoCursoAfetoImpl cursoAfeto = null;
        //todo fazer aqui um teste a ver se na lista de unidades found vem as unidades do curso afeto
        //reativar o set e testar isso
        List<QuestionarioPedagogicoCursoAfeto> cursosFound = DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().find(q.getId(),c.getCode());
        if(cursosFound != null && cursosFound.size() > 1)
        {
            msg = "Encontrados mais que um curso nos mesmos códigos:" + c.getCode() + " apagando um";
            serviceLogWarn(msg);
            logger.warn(msg);
            logMessages.addMessage(new DefaultLogMessage("questionario.courses.selection", LogMessageTypeEnum.WARNING,msg));
            cursoAfeto = (QuestionarioPedagogicoCursoAfetoImpl) cursosFound.get(0);
            cursosFound.remove(0);
            for(QuestionarioPedagogicoCursoAfeto ca: cursosFound)
                removeCursoAfeto(ca);
        }
        else if(cursosFound != null && cursosFound.size() == 1)
        {
            msg = "Curso " + c.getCode() + " encontrado, vai atualizar";
            serviceLogInfo(msg);
            logger.info(msg);
            cursoAfeto = (QuestionarioPedagogicoCursoAfetoImpl) cursosFound.get(0);
        }
        else
        {
            msg = "Criando novo curso para o código " + c.getCode();
            serviceLogInfo(msg);
            logger.info(msg);
            cursoAfeto = DomainObjectFactory.createQuestionarioPedagogicoCursoAfeto();
            DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().save(cursoAfeto);
            cursoAfeto.setUnidadesAfetas(new HashSet<QuestionarioPedagogicoUnidadeCurricularAfeta>());
        }

        cursoAfeto.resetStats();

        cursoAfeto.setCourse(c);
        cursoAfeto.setCodigoInstituicao(c.getInstitutionalCode());
        cursoAfeto.setNomeInstituicao(ConfigProperties.getProperty("institution.code."+c.getInstitutionalCode()));
        cursoAfeto.setAno(q.getYear());
        cursoAfeto.setCodigoCurso(c.getCode());
        cursoAfeto.setNome(c.getName());
        cursoAfeto.setQuestionario(q);
        cursoAfeto.setSemestre(q.getSemestre());




        List<String> newUnitCodesList = new ArrayList<String>();
        int countUnits = 0;
        List<CourseUnitDaoImpl.CourseUnitResult> results = DaoFactory.getCourseUnitDaoImpl().loadCourseUnits(c.getId(), q.getSemestre(), q.getYear());
        int totalUnits =  results.size();
        for(CourseUnitDaoImpl.CourseUnitResult cur : results)
        {
            countUnits++;
            CourseUnit cu = DaoFactory.getCourseUnitDaoImpl().load(cur.id);
            newUnitCodesList.add(cu.getCode());
            /** logging **/
            msg = "---->(" + countUnits + " of " + totalUnits  +") CourseUnit loaded: " + cu.getName() + "(" + cu.getCode() + ")";
            serviceLogInfo(msg);
            logger.info(msg);
            /** logging **/
            createUnidadeAfeta(cursoAfeto, cur,cu, logMessages);
            DaoFactory.getCourseUnitDaoImpl().evict(cu);
        }

        removeUnselectedUnits(cursoAfeto,newUnitCodesList);
    }

    /**
     *
     * @param cursoAfeto
     * @param cur
     * @throws IOException
     * @throws TransformationException
     */

    private void createUnidadeAfeta(QuestionarioPedagogicoCursoAfetoImpl cursoAfeto, CourseUnitDaoImpl.CourseUnitResult cur, CourseUnit cu, DefaultLogMessages logMessages) throws 1.5.0/docs/api/java/io/IOException.html">IOException, TransformationException {

        1.5.0/docs/api/java/lang/String.html">String msg;
        QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeAfeta = null;
        List<QuestionarioPedagogicoUnidadeCurricularAfeta> unidadesFound = DaoFactory.getQuestionarioPedagogicoUnidadeCurricularAfetaDaoImpl().find(cursoAfeto.getQuestionario().getId(), cursoAfeto.getCodigoCurso(), cu.getCode());
        if(unidadesFound != null && unidadesFound.size() > 1)
        {
            msg = "Encontradas mais que uma unidade nos mesmos códigos: curso:" +cursoAfeto.getCodigoCurso() + ", unidade " + cu.getCode() + " apagando um";
            serviceLogWarn(msg);
            logger.warn(msg);
            logMessages.addMessage(new DefaultLogMessage("questionario.courses.selection", LogMessageTypeEnum.WARNING,msg));
            unidadeAfeta = (QuestionarioPedagogicoUnidadeCurricularAfetaImpl) unidadesFound.get(0);
            unidadesFound.remove(0);
            DaoFactory.getQuestionarioPedagogicoUnidadeCurricularAfetaDaoImpl().delete(unidadesFound);
        }
        else if(unidadesFound != null && unidadesFound.size() == 1)
        {
            msg = "Unidade " +  cu.getCode() + " encontrada, vai atualizar";
            serviceLogInfo(msg);
            logger.info(msg);
            unidadeAfeta = (QuestionarioPedagogicoUnidadeCurricularAfetaImpl) unidadesFound.get(0);
        }
        else
        {
            msg = "Criando nova unidade para o código " + cu.getCode();
            serviceLogInfo(msg);
            logger.info(msg);
            unidadeAfeta = DomainObjectFactory.createQuestionarioPedagogicoUnidadeCurricularAfeta();
            unidadeAfeta.setUsar(true);
            unidadeAfeta.setVista(false);
            DaoFactory.getQuestionarioPedagogicoUnidadeCurricularAfetaDaoImpl().save(unidadeAfeta);
        }

        unidadeAfeta.resetStats();
        unidadeAfeta.setCursoAfeto(cursoAfeto);//so metemos de um dos lados
        unidadeAfeta.setCourseUnit(cu);
        unidadeAfeta.setCodigoUnidade(cu.getCode());
        unidadeAfeta.setObs("");
        unidadeAfeta.setNome(cu.getName());

        unidadeAfeta.setMarked(false);

        ArrayList<CourseUnitImpl.Tipologia> mergedTipologias = copiarTipologias(cu, unidadeAfeta);


        checkTurmaAndProfs(cu, unidadeAfeta, mergedTipologias);
        checkProfs(cur, unidadeAfeta);
        checkTurmas(cur, unidadeAfeta);
        checkStudents(cur, unidadeAfeta);


        if(unidadeAfeta.isMarked())
            cursoAfeto.incMarcadas();


    }

    /**
     *
     * @param cur
     * @param unidadeAfeta
     */

    private void checkTurmas(CourseUnitDaoImpl.CourseUnitResult cur, QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeAfeta) {
        if(cur.turmas == 0)
        {
            unidadeAfeta.setTurmas(0);
            unidadeAfeta.setMarked(true); //WARNING
            unidadeAfeta.addObs("Não tem turmas");
        }
        else
            unidadeAfeta.setTurmas(cur.turmas);
    }

    /**
     *
     * @param cur
     * @param unidadeAfeta
     */

    private void checkProfs(CourseUnitDaoImpl.CourseUnitResult cur, QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeAfeta) {
        if(cur.teachers == 0)
        {
            unidadeAfeta.setProfs(0);
            unidadeAfeta.setMarked(true); //WARNING
            unidadeAfeta.addObs("Não tem professores");
        }
        else
            unidadeAfeta.setProfs(cur.teachers);
    }

    /**
     *
     * @param cur
     * @param unidadeAfeta
     */

    private void checkStudents(CourseUnitDaoImpl.CourseUnitResult cur, QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeAfeta) {
        if(cur.students == 0)
        {
            unidadeAfeta.setStudents(0);
            unidadeAfeta.setMarked(true); //WARNING
            unidadeAfeta.addObs("Não tem estudantes");
        }
        else
            unidadeAfeta.setStudents(cur.students);
    }

    /**
     *
     * @param cu
     * @param unidadeAfeta
     * @return
     * @throws IOException
     * @throws TransformationException
     */

    private ArrayList<CourseUnitImpl.Tipologia> copiarTipologias(CourseUnit cu, QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeAfeta) throws 1.5.0/docs/api/java/io/IOException.html">IOException, TransformationException {
        try
        {
            CourseUnitImpl.Tipologias tipologias = ((CourseUnitImpl)cu).getTipologiasClass();
            ArrayList<CourseUnitImpl.Tipologia> mergedTipologias = tipologias.obtainMergeTipologias();
            unidadeAfeta.setTipologias(mergedTipologias.size());
            unidadeAfeta.setTipologiasJson(CourseUnitImpl.Tipologias.serializeMergedList(mergedTipologias));
            unidadeAfeta.setAddedTipologias(tipologias.getTipologiasExtraAdicionadas().size());
            return mergedTipologias;
        }
        catch(1.5.0/docs/api/java/lang/Throwable.html">Throwable e)
        {
            ArrayList<CourseUnitImpl.Tipologia> tipologias = new ArrayList<CourseUnitImpl.Tipologia>();
            unidadeAfeta.setMarked(true);
            unidadeAfeta.addObs("Erro a descodificar tipologias");
            unidadeAfeta.setTipologiasJson(CourseUnitImpl.Tipologias.serializeMergedList(tipologias));
            return tipologias;
        }
    }

    /**
     *
     * @param cu
     * @param unidadeAfeta
     * @param mergedTipologias
     */

    private void checkTurmaAndProfs(CourseUnit cu, QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeAfeta, ArrayList<CourseUnitImpl.Tipologia> mergedTipologias) {
        if(cu.getTeachers() != null)
        {
            HashMap<String,Boolean> turmaWithProfs = new HashMap<String, Boolean>();
            HashMap<String,Boolean> profsWithTurma = new HashMap<String, Boolean>();
            for(CourseUnitImpl.Tipologia t: mergedTipologias)
            {
                turmaWithProfs.put(t.getCdTurma(),true);
                profsWithTurma.put(t.getCdDocente(),true);
            }
            for(Teacher t: cu.getTeachers())
            {
                if(profsWithTurma.get(""+t.getSigesCode())==null)
                {
                    unidadeAfeta.setProfsWithoutTurma(unidadeAfeta.getProfsWithoutTurma()+1);
                    unidadeAfeta.setMarked(true);
                }
                DaoFactory.getTeacherDaoImpl().evict(t);
            }

            for(CourseUnitTurma t: cu.getTurmas())
            {
                if(turmaWithProfs.get(t.getTurma())==null)
                {
                    unidadeAfeta.setTurmaWithoutProf(unidadeAfeta.getTurmaWithoutProf() + 1);
                    unidadeAfeta.setMarked(true);
                }
                DaoFactory.getCourseUnitTurmaDaoImpl().evict(t);
            }
        }
    }


    /**
     * SERVIÇO
     * @param questionarioId
     * @param cursosAfetos
     * @param session
     * @param questionarioCleared
     * @throws IOException
     * @throws TransformationException
     * @throws NotAuthorizedException
     */

    public void updateTipologiasPedagogico(long questionarioId, List<QuestionarioPedagogicoCursoAfeto> cursosAfetos, UserSession session,QuestionarioImpl questionarioCleared) throws 1.5.0/docs/api/java/io/IOException.html">IOException, TransformationException, NotAuthorizedException {

        if(!questionarioCleared.isClear((UserSessionImpl) session,QuestionarioImpl.QuestionarioClearancesOperation.QUESTIONARIO_CHANGE_TIPOLOGIES.name()))
        {
            throw new NotAuthorizedException("Nao tem autorização para alterar as tipologias");
        }
        for(QuestionarioPedagogicoCursoAfeto cursoAfeto: cursosAfetos)
        {
            QuestionarioPedagogicoCursoAfeto cuAfetoPersistent = DaoFactory.getQuestionarioPedagogicoCursoAfetoDaoImpl().load(cursoAfeto.getId());
            if(cuAfetoPersistent.getQuestionario().getId() == questionarioId)
            {
                cuAfetoPersistent.setUsarTipologias(cursoAfeto.isUsarTipologias());
            }
            else
                logger.warn("Curso pedido no serviço não faz parte do questionario requisitado: " + cursoAfeto.getId() + " " + cursoAfeto.getQuestionario().getId() + " != " + questionarioId);

        }

    }

    public void updateCheckVarPedagogico(long questionarioId,long unidadeAfetaId, 1.5.0/docs/api/java/lang/String.html">String op,1.5.0/docs/api/java/lang/String.html">String val,UserSession session, QuestionarioImpl questionarioCleared) throws NotAuthorizedException {

        if(!questionarioCleared.isClear((UserSessionImpl) session,QuestionarioImpl.QuestionarioClearancesOperation.QUESTIONARIO_CHANGE_ASSIGNEMENTS_CHECK_TEACHERS.name()) &&
                !questionarioCleared.isClear((UserSessionImpl) session,QuestionarioImpl.QuestionarioClearancesOperation.QUESTIONARIO_CHANGE_ASSIGNEMENTS.name()) &&
                !questionarioCleared.isClear((UserSessionImpl) session,QuestionarioImpl.QuestionarioClearancesOperation.QUESTIONARIO_CHANGE_TIPOLOGIES.name()))
        {
            throw new NotAuthorizedException("Nao tem autorização para alterar as tipologias");
        }
        QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidade = (QuestionarioPedagogicoUnidadeCurricularAfetaImpl) DaoFactory.getQuestionarioPedagogicoUnidadeCurricularAfetaDaoImpl().load(unidadeAfetaId);
        if(op.equals("usar"))
        {
            unidade.setUsar(1.5.0/docs/api/java/lang/Boolean.html">Boolean.parseBoolean(val));
        }
        else if(op.equals("vista"))
        {
            unidade.setVista(1.5.0/docs/api/java/lang/Boolean.html">Boolean.parseBoolean(val));
        }
        else if(op.equals("vistaProfs"))
        {
            unidade.setVistaProfs(1.5.0/docs/api/java/lang/Boolean.html">Boolean.parseBoolean(val));
        }
        else if(op.equals("observacoes"))
        {
            unidade.setObs(val);
        }
    }

}