org.fenixedu.ulisboa.specifications.servlet.FenixeduUlisboaSpecificationsInitializer.java Source code

Java tutorial

Introduction

Here is the source code for org.fenixedu.ulisboa.specifications.servlet.FenixeduUlisboaSpecificationsInitializer.java

Source

/**
 * This file was created by Quorum Born IT <http://www.qub-it.com/> and its 
 * copyright terms are bind to the legal agreement regulating the FenixEdu@ULisboa 
 * software development project between Quorum Born IT and Servios Partilhados da
 * Universidade de Lisboa:
 *  - Copyright  2015 Quorum Born IT (until any Go-Live phase)
 *  - Copyright  2015 Universidade de Lisboa (after any Go-Live phase)
 *
 *
 * 
 * This file is part of FenixEdu fenixedu-ulisboa-specifications.
 *
 * FenixEdu Specifications is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FenixEdu Specifications is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with FenixEdu Specifications.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fenixedu.ulisboa.specifications.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.apache.commons.lang.StringUtils;
import org.fenixedu.academic.domain.Attends;
import org.fenixedu.academic.domain.Degree;
import org.fenixedu.academic.domain.Enrolment;
import org.fenixedu.academic.domain.EvaluationConfiguration;
import org.fenixedu.academic.domain.GradeScale;
import org.fenixedu.academic.domain.GradeScale.GradeScaleLogic;
import org.fenixedu.academic.domain.SchoolClass;
import org.fenixedu.academic.domain.curricularRules.EnrolmentPeriodRestrictionsInitializer;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.student.Registration;
import org.fenixedu.academic.domain.studentCurriculum.Credits;
import org.fenixedu.academic.domain.studentCurriculum.Dismissal;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.groups.DynamicGroup;
import org.fenixedu.bennu.core.servlets.ExceptionHandlerFilter;
import org.fenixedu.bennu.core.util.CoreConfiguration;
import org.fenixedu.bennu.portal.domain.PortalConfiguration;
import org.fenixedu.bennu.portal.servlet.PortalDevModeExceptionHandler;
import org.fenixedu.bennu.portal.servlet.PortalExceptionHandler;
import org.fenixedu.bennu.signals.Signal;
import org.fenixedu.learning.domain.degree.DegreeSite;
import org.fenixedu.ulisboa.specifications.ULisboaConfiguration;
import org.fenixedu.ulisboa.specifications.authentication.ULisboaAuthenticationRedirector;
import org.fenixedu.ulisboa.specifications.domain.ExtendedDegreeInfo;
import org.fenixedu.ulisboa.specifications.domain.MaximumNumberOfCreditsForEnrolmentPeriodEnforcer;
import org.fenixedu.ulisboa.specifications.domain.RegistrationObservations;
import org.fenixedu.ulisboa.specifications.domain.ULisboaPortalConfiguration;
import org.fenixedu.ulisboa.specifications.domain.ULisboaSpecificationsRoot;
import org.fenixedu.ulisboa.specifications.domain.UsernameSequenceGenerator;
import org.fenixedu.ulisboa.specifications.domain.curricularRules.AnyCurricularCourseExceptionsInitializer;
import org.fenixedu.ulisboa.specifications.domain.curricularRules.executors.ruleExecutors.CurricularRuleConfigurationInitializer;
import org.fenixedu.ulisboa.specifications.domain.ects.CourseGradingTable;
import org.fenixedu.ulisboa.specifications.domain.ects.DegreeGradingTable;
import org.fenixedu.ulisboa.specifications.domain.evaluation.EnrolmentEvaluationExtendedInformation;
import org.fenixedu.ulisboa.specifications.domain.evaluation.EvaluationComparator;
import org.fenixedu.ulisboa.specifications.domain.evaluation.config.MarkSheetSettings;
import org.fenixedu.ulisboa.specifications.domain.evaluation.season.EvaluationSeasonServices;
import org.fenixedu.ulisboa.specifications.domain.serviceRequests.ServiceRequestOutputType;
import org.fenixedu.ulisboa.specifications.domain.serviceRequests.ServiceRequestSlot;
import org.fenixedu.ulisboa.specifications.domain.serviceRequests.ULisboaServiceRequest;
import org.fenixedu.ulisboa.specifications.domain.serviceRequests.processors.ULisboaServiceRequestProcessor;
import org.fenixedu.ulisboa.specifications.domain.student.EnrolmentPredicateInitializer;
import org.fenixedu.ulisboa.specifications.domain.student.RegistrationDataByExecutionYearExtendedInformation;
import org.fenixedu.ulisboa.specifications.domain.student.RegistrationExtendedInformation;
import org.fenixedu.ulisboa.specifications.domain.student.RegistrationRegimeVerifierInitializer;
import org.fenixedu.ulisboa.specifications.domain.student.curriculum.CurriculumConfigurationInitializer;
import org.fenixedu.ulisboa.specifications.domain.studentCurriculum.CurriculumLineExtendedInformation;
import org.fenixedu.ulisboa.specifications.domain.studentCurriculum.EctsAndWeightProviders;
import org.fenixedu.ulisboa.specifications.domain.studentCurriculum.EnrolmentManagerFactoryInitializer;
import org.fenixedu.ulisboa.specifications.domain.studentCurriculum.StudentScheduleListeners;
import org.fenixedu.ulisboa.specifications.task.tmp.FixBugProcessorTypeTask;
import org.fenixedu.ulisboa.specifications.task.tmp.UpdateServiceRequestType;
import org.fenixedu.ulisboa.specifications.ui.blue_record.authentication.BlueRecordRedirector;
import org.fenixedu.ulisboa.specifications.ui.renderers.student.curriculum.CurriculumLayout;
import org.fenixedu.ulisboa.specifications.ui.renderers.student.curriculum.StudentCurricularPlanLayout;
import org.fenixedu.ulisboa.specifications.ui.student.enrolment.process.EnrolmentProcess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.Atomic.TxMode;
import pt.ist.fenixframework.FenixFramework;
import pt.ist.fenixframework.dml.DeletionListener;
import pt.ist.fenixframework.dml.runtime.RelationAdapter;

@WebListener
public class FenixeduUlisboaSpecificationsInitializer implements ServletContextListener {

    private static final Logger logger = LoggerFactory.getLogger(FenixeduUlisboaSpecificationsInitializer.class);

    public static final String BUNDLE = "resources/FenixeduUlisboaSpecificationsResources";

    @Override
    public void contextDestroyed(ServletContextEvent event) {
    }

    @Atomic(mode = TxMode.SPECULATIVE_READ)
    @Override
    public void contextInitialized(ServletContextEvent event) {
        ULisboaSpecificationsRoot.init();
        MarkSheetSettings.init();
        configurePortal();
        configureGradeScaleLogics();
        configureMaximumNumberOfCreditsForEnrolmentPeriod();
        EctsAndWeightProviders.init();
        EnrolmentPeriodRestrictionsInitializer.init();
        EnrolmentProcess.init();
        CurriculumConfigurationInitializer.init();
        AnyCurricularCourseExceptionsInitializer.init();
        CurricularRuleConfigurationInitializer.init();
        RegistrationRegimeVerifierInitializer.init();
        EnrolmentPredicateInitializer.init();
        EnrolmentManagerFactoryInitializer.init();
        EvaluationSeasonServices.initialize();
        StudentCurricularPlanLayout.register();
        CurriculumLayout.register();
        configureEnrolmentEvaluationComparator();

        UsernameSequenceGenerator usernameSequenceGenerator = ULisboaSpecificationsRoot.getInstance()
                .getUsernameSequenceGenerator();
        if (usernameSequenceGenerator == null) {
            usernameSequenceGenerator = new UsernameSequenceGenerator();
            ULisboaSpecificationsRoot.getInstance().setUsernameSequenceGenerator(usernameSequenceGenerator);
        }
        User.setUsernameGenerator(usernameSequenceGenerator);
        DynamicGroup dynamicGroup = org.fenixedu.bennu.core.groups.DynamicGroup.get("employees");
        if (!dynamicGroup.isDefined()) {
            dynamicGroup.toPersistentGroup();
        }

        setupCustomExceptionHandler(event);
        setupListenerForDegreeDelete();
        setupListenerForEnrolmentDelete();
        setupListenerForSchoolClassDelete();
        setupListenersForStudentSchedule();
        setupListenerForInvalidEquivalences();
        ULisboaServiceRequest.setupListenerForPropertiesDeletion();
        ULisboaServiceRequest.setupListenerForServiceRequestTypeDeletion();

        ServiceRequestSlot.initStaticSlots();
        ServiceRequestOutputType.initOutputTypes();
        ULisboaServiceRequestProcessor.initValidators();

        try {
            new UpdateServiceRequestType().runTask();
            new FixBugProcessorTypeTask().runTask();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        CourseGradingTable.registerProvider();
        DegreeGradingTable.registerProvider();

        ExtendedDegreeInfo.setupDeleteListener();
        ExtendedDegreeInfo.setupCreationListener();

        RegistrationObservations.setupDeleteListener();

        CurriculumLineExtendedInformation.setupDeleteListener();

        EnrolmentEvaluationExtendedInformation.setupDeleteListener();

        RegistrationExtendedInformation.setupDeleteListener();

        RegistrationDataByExecutionYearExtendedInformation.setupDeleteListener();

        ULisboaAuthenticationRedirector.registerRedirectionHandler(new BlueRecordRedirector());

    }

    private void setupListenerForDegreeDelete() {
        //we need to delete FirstTime Configuration when a degree is deleted
        //        Degree.getRelationDegreeFirstYearRegistrationConfiguration().removeListener(new Relation

        FenixFramework.getDomainModel().registerDeletionListener(Degree.class, new DeletionListener<Degree>() {

            @Override
            public void deleting(Degree degree) {
                degree.getFirstYearRegistrationConfigurationsSet().forEach(c -> c.delete());

                DegreeSite site = degree.getSite();
                if (site != null) {
                    site.delete();
                }
            }
        });
    }

    private void setupListenerForEnrolmentDelete() {
        Attends.getRelationAttendsEnrolment().addListener(new RelationAdapter<Enrolment, Attends>() {
            @Override
            public void beforeRemove(Enrolment enrolment, Attends attends) {
                final Registration registration = attends.getRegistration();
                if (registration != null) {
                    attends.getExecutionCourse().getAssociatedShifts().forEach(s -> s.removeStudents(registration));
                }
            }
        });
    }

    private void setupListenerForSchoolClassDelete() {
        FenixFramework.getDomainModel().registerDeletionListener(SchoolClass.class,
                new DeletionListener<SchoolClass>() {

                    @Override
                    public void deleting(SchoolClass schoolClass) {
                        schoolClass.getRegistrationsSet().clear();
                        schoolClass.setNextSchoolClass(null);
                        schoolClass.getPreviousSchoolClassesSet().clear();
                    }
                });
    }

    private void setupListenerForInvalidEquivalences() {
        Dismissal.getRelationCreditsDismissalEquivalence().addListener(new RelationAdapter<Dismissal, Credits>() {
            @Override
            public void beforeAdd(Dismissal dismissal, Credits credits) {
                if (credits != null && dismissal != null
                        && (dismissal.isCreditsDismissal() || dismissal.isOptional()) && credits.isEquivalence()) {
                    throw new DomainException("error.Equivalence.can.only.be.applied.to.curricular.courses");

                }
            }
        });
    }

    private void setupListenersForStudentSchedule() {
        Signal.register(Enrolment.SIGNAL_CREATED, StudentScheduleListeners.SHIFTS_ENROLLER);
    }

    static private void configureEnrolmentEvaluationComparator() {
        EvaluationConfiguration.setEnrolmentEvaluationOrder(new EvaluationComparator());
    }

    static private void configurePortal() {
        ULisboaPortalConfiguration ulisboaPortal = PortalConfiguration.getInstance().getUlisboaPortal();
        if (ulisboaPortal == null) {
            ulisboaPortal = new ULisboaPortalConfiguration();
            ulisboaPortal.setPortal(PortalConfiguration.getInstance());
        }
    }

    static private void configureGradeScaleLogics() {
        configureType20GradeScaleLogic();
        configureTypeQualitativeGradeScaleLogic();
    }

    static private void configureTypeQualitativeGradeScaleLogic() {
        final GradeScaleLogic logic = loadClass("gradescale.typequalitative.logic.class",
                ULisboaConfiguration.getConfiguration().typeQualitativeGradeScaleLogic());

        if (logic != null) {
            GradeScale.TYPEQUALITATIVE.setLogic(logic);
        }
    }

    static private void configureType20GradeScaleLogic() {
        final GradeScaleLogic logic = loadClass("gradescale.type20.logic.class",
                ULisboaConfiguration.getConfiguration().type20GradeScaleLogic());

        if (logic != null) {
            GradeScale.TYPE20.setLogic(logic);
        }
    }

    @SuppressWarnings("unchecked")
    static private <T> T loadClass(final String key, final String value) {
        T result = null;

        try {

            if (StringUtils.isNotBlank(value)) {
                result = (T) Class.forName(value).newInstance();
            } else {

                final String message = "Property [" + key + "] must be defined in configuration file";
                if (CoreConfiguration.getConfiguration().developmentMode()) {
                    logger.error("{}. Empty value may lead to wrong system behaviour", message);
                } else {
                    throw new RuntimeException(message);
                }
            }

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("An error occured loading class: " + value, e);
        }

        if (result != null) {
            logger.info("Using " + result.getClass().getSimpleName());
        }

        return result;
    }

    static private void configureMaximumNumberOfCreditsForEnrolmentPeriod() {
        final MaximumNumberOfCreditsForEnrolmentPeriodEnforcer enforcer = MaximumNumberOfCreditsForEnrolmentPeriodEnforcer
                .getInstance();

        if (enforcer != null) {
            enforcer.delete();
        }
    }

    private void setupCustomExceptionHandler(ServletContextEvent event) {
        ServletContext servletContext = event.getServletContext();
        PortalExceptionHandler exceptionHandler = CoreConfiguration.getConfiguration()
                .developmentMode() == Boolean.TRUE ? new PortalDevModeExceptionHandler(servletContext)
                        : new PortalExceptionHandler(servletContext);
        ExceptionHandlerFilter.setExceptionHandler(new FenixEduUlisboaExceptionHandler(exceptionHandler));
    }

}