/**
* Copyright © 2002 Instituto Superior Técnico
*
* This file is part of FenixEdu Academic.
*
* FenixEdu Academic 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 Academic 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 Academic. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.academic.ui.faces.bean.scientificCouncil.curricularPlans;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import org.fenixedu.academic.domain.Degree;
import org.fenixedu.academic.domain.DegreeCurricularPlan;
import org.fenixedu.academic.domain.ExecutionYear;
import org.fenixedu.academic.domain.GradeScale;
import org.fenixedu.academic.domain.degree.degreeCurricularPlan.DegreeCurricularPlanState;
import org.fenixedu.academic.domain.degreeStructure.CurricularStage;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.person.RoleType;
import org.fenixedu.academic.domain.time.calendarStructure.AcademicPeriod;
import org.fenixedu.academic.domain.time.calendarStructure.AcademicYears;
import org.fenixedu.academic.dto.InfoExecutionYear;
import org.fenixedu.academic.predicate.IllegalDataAccessException;
import org.fenixedu.academic.service.services.commons.ReadCurrentExecutionYear;
import org.fenixedu.academic.service.services.commons.ReadNotClosedExecutionYears;
import org.fenixedu.academic.service.services.exceptions.FenixServiceException;
import org.fenixedu.academic.service.services.scientificCouncil.curricularPlans.CreateDegreeCurricularPlan;
import org.fenixedu.academic.service.services.scientificCouncil.curricularPlans.DeleteDegreeCurricularPlan;
import org.fenixedu.academic.service.services.scientificCouncil.curricularPlans.EditDegreeCurricularPlan;
import org.fenixedu.academic.ui.faces.bean.base.FenixBackingBean;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.groups.Group;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.FenixFramework;
public class DegreeCurricularPlanManagementBackingBean extends FenixBackingBean {
private static final String NO_SELECTION = "noSelection";
private String degreeId;
private String dcpId;
private DegreeCurricularPlan dcp;
private String name;
private String gradeScale;
private String[] selectedGroupMembersToDelete;
private String newGroupMember;
private String durationTypeName;
private List<SelectItem> durationTypes = null;
public String getAction() {
return getAndHoldStringParameter("action");
}
public String getNewGroupMember() {
return newGroupMember == null ? newGroupMember = getAndHoldStringParameter("newGroupMember") : newGroupMember;
}
public void setNewGroupMember(String newGroupMember) {
this.newGroupMember = newGroupMember;
}
public String getDegreeId() {
return (degreeId == null) ? (degreeId = getAndHoldStringParameter("degreeId")) : degreeId;
}
public String getDcpId() {
if (dcp == null) {
if (getAndHoldStringParameter("dcpId") != null) {
dcpId = getAndHoldStringParameter("dcpId");
} else {
dcpId = getAndHoldStringParameter("degreeCurricularPlanID");
}
}
return dcpId;
}
public void setDcpId(String dcpId) {
this.dcpId = dcpId;
}
public DegreeCurricularPlan getDcp() {
return (dcp == null) ? (dcp = FenixFramework.getDomainObject(getDcpId())) : dcp;
}
public void setDcp(DegreeCurricularPlan dcp) {
this.dcp = dcp;
}
public List<String> getGroupMembersLabels() {
return getGroupMembers().stream().map(SelectItem::getLabel).collect(Collectors.toList());
}
public List<SelectItem> getGroupMembers() {
List<SelectItem> result = new ArrayList<SelectItem>();
Group curricularPlanMembersGroup = getDcp().getCurricularPlanMembersGroup();
if (curricularPlanMembersGroup != null) {
curricularPlanMembersGroup.getMembers().forEach(
user -> result.add(new SelectItem(user.getExternalId(), user.getPerson().getName() + " ("
+ user.getUsername() + ")")));
}
return result;
}
@Atomic
public void addUserToGroup() {
if (getNewGroupMember() != null) {
User user = User.findByUsername(getNewGroupMember());
if (user != null) {
Group group = getDcp().getCurricularPlanMembersGroup();
getDcp().setCurricularPlanMembersGroup(group.grant(user));
RoleType.grant(RoleType.BOLONHA_MANAGER, user);
}
}
}
@Atomic
public void removeUsersFromGroup(ActionEvent event) {
if (selectedGroupMembersToDelete != null && selectedGroupMembersToDelete.length > 0) {
Group group = getDcp().getCurricularPlanMembersGroup();
for (String userExternalId : selectedGroupMembersToDelete) {
User user = FenixFramework.getDomainObject(userExternalId);
if (user != null) {
group = group.revoke(user);
removeRoleIfNecessary(user);
}
}
getDcp().setCurricularPlanMembersGroup(group);
}
}
private boolean isUserMemberOfAnyCurricularPlanGroup(User user) {
return Degree.readBolonhaDegrees().stream().flatMap(d -> d.getDegreeCurricularPlansSet().stream())
.filter(dcp -> !dcp.equals(getDcp())).anyMatch(dcp -> dcp.getCurricularPlanMembersGroup().isMember(user));
}
private boolean isUserMemberOfAnyDepartmentCompetenceCourseGroup(User user) {
return Bennu.getInstance().getDepartmentsSet().stream().anyMatch(d -> d.getCompetenceCourseMembersGroup().isMember(user));
}
private void removeRoleIfNecessary(User user) {
if (!isUserMemberOfAnyCurricularPlanGroup(user) && !isUserMemberOfAnyDepartmentCompetenceCourseGroup(user)) {
RoleType.revoke(RoleType.BOLONHA_MANAGER, user);
}
}
public String getName() {
return (name == null && getDcp() != null) ? (name = getDcp().getName()) : name;
}
public void setName(String name) {
this.name = name;
}
public String getCurricularStage() {
if (getViewState().getAttribute("curricularStage") == null && getDcp() != null) {
setCurricularStage(getDcp().getCurricularStage().getName());
}
return (String) getViewState().getAttribute("curricularStage");
}
public void setCurricularStage(String curricularStage) {
getViewState().setAttribute("curricularStage", curricularStage);
}
public String getState() {
if (getViewState().getAttribute("state") == null && getDcp() != null) {
setState(getDcp().getState().getName());
}
return (String) getViewState().getAttribute("state");
}
public void setState(String state) {
getViewState().setAttribute("state", state);
}
public String getGradeScale() {
return (gradeScale == null && getDcp() != null) ? (gradeScale = getDcp().getGradeScale().getName()) : gradeScale;
}
public void setGradeScale(String gradeScale) {
this.gradeScale = gradeScale;
}
public List<SelectItem> getGradeScales() {
List<SelectItem> result = new ArrayList<SelectItem>();
result.add(new SelectItem(this.NO_SELECTION, BundleUtil.getString(Bundle.SCIENTIFIC, "choose")));
result.add(new SelectItem(GradeScale.TYPE20.name(), BundleUtil.getString(Bundle.ENUMERATION, GradeScale.TYPE20.name())));
result.add(new SelectItem(GradeScale.TYPE5.name(), BundleUtil.getString(Bundle.ENUMERATION, GradeScale.TYPE5.name())));
return result;
}
public String createCurricularPlan() {
// valueOf
// (this.
// gradeScale)
// };
try {
CreateDegreeCurricularPlan.run(this.getDegreeId(), this.name, null, getDuration());
} catch (IllegalDataAccessException e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "error.notAuthorized"));
return "curricularPlansManagement";
} catch (FenixServiceException e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, e.getMessage()));
return "";
} catch (DomainException e) {
addErrorMessage(BundleUtil.getString(Bundle.DOMAIN_EXCEPTION, e.getKey(), e.getArgs()));
return "";
} catch (Exception e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "error.creatingDegreeCurricularPlan"));
return "curricularPlansManagement";
}
this.addInfoMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "degreeCurricularPlan.created"));
return "curricularPlansManagement";
}
public List<SelectItem> getCurricularStages() {
List<SelectItem> result = new ArrayList<SelectItem>();
if (getDcp().getExecutionDegreesSet().isEmpty()) {
result.add(new SelectItem(CurricularStage.DRAFT.name(), BundleUtil.getString(Bundle.ENUMERATION,
CurricularStage.DRAFT.getName())));
}
result.add(new SelectItem(CurricularStage.PUBLISHED.name(), BundleUtil.getString(Bundle.ENUMERATION,
CurricularStage.PUBLISHED.getName())));
result.add(new SelectItem(CurricularStage.APPROVED.name(), BundleUtil.getString(Bundle.ENUMERATION,
CurricularStage.APPROVED.getName())));
return result;
}
public List<SelectItem> getStates() {
List<SelectItem> result = new ArrayList<SelectItem>();
result.add(new SelectItem(DegreeCurricularPlanState.ACTIVE.name(), BundleUtil.getString(Bundle.ENUMERATION,
DegreeCurricularPlanState.ACTIVE.getName())));
result.add(new SelectItem(DegreeCurricularPlanState.NOT_ACTIVE.name(), BundleUtil.getString(Bundle.ENUMERATION,
DegreeCurricularPlanState.NOT_ACTIVE.getName())));
result.add(new SelectItem(DegreeCurricularPlanState.CONCLUDED.name(), BundleUtil.getString(Bundle.ENUMERATION,
DegreeCurricularPlanState.CONCLUDED.getName())));
result.add(new SelectItem(DegreeCurricularPlanState.PAST.name(), BundleUtil.getString(Bundle.ENUMERATION,
DegreeCurricularPlanState.PAST.getName())));
return result;
}
public String getExecutionYearID() {
return (String) getViewState().getAttribute("executionYearID");
}
public void setExecutionYearID(String executionYearID) {
getViewState().setAttribute("executionYearID", executionYearID);
}
public List<SelectItem> getExecutionYearItems() throws FenixServiceException {
final List<SelectItem> result = new ArrayList<SelectItem>();
final InfoExecutionYear currentInfoExecutionYear = ReadCurrentExecutionYear.run();
final List<InfoExecutionYear> notClosedInfoExecutionYears = ReadNotClosedExecutionYears.run();
for (final InfoExecutionYear notClosedInfoExecutionYear : notClosedInfoExecutionYears) {
if (notClosedInfoExecutionYear.after(currentInfoExecutionYear)) {
result.add(new SelectItem(notClosedInfoExecutionYear.getExternalId(), notClosedInfoExecutionYear.getYear()));
}
}
result.add(0, new SelectItem(currentInfoExecutionYear.getExternalId(), currentInfoExecutionYear.getYear()));
setDefaultExecutionYearIDIfExisting();
return result;
}
private void setDefaultExecutionYearIDIfExisting() {
final DegreeCurricularPlan dcp = getDcp();
if (dcp != null) {
final List<ExecutionYear> executionYears =
new ArrayList<ExecutionYear>(dcp.getRoot().getBeginContextExecutionYears());
Collections.sort(executionYears, ExecutionYear.COMPARATOR_BY_YEAR);
if (!executionYears.isEmpty()) {
setExecutionYearID(executionYears.iterator().next().getExternalId());
}
}
}
public String editCurricularPlan() {
try {
EditDegreeCurricularPlan.run(getDcpId(), getName(), CurricularStage.valueOf(getCurricularStage()),
DegreeCurricularPlanState.valueOf(getState()), null, getExecutionYearID(), getDuration());
} catch (IllegalDataAccessException e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "error.notAuthorized"));
return "curricularPlansManagement";
} catch (FenixServiceException e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, e.getMessage()));
return "";
} catch (DomainException e) {
addErrorMessage(BundleUtil.getString(Bundle.DOMAIN_EXCEPTION, e.getKey(), e.getArgs()));
return "";
} catch (Exception e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "error.editingDegreeCurricularPlan"));
return "curricularPlansManagement";
}
this.addInfoMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "degreeCurricularPlan.edited"));
return "curricularPlansManagement";
}
public String deleteCurricularPlan() {
try {
DeleteDegreeCurricularPlan.run(this.getDcpId());
} catch (IllegalDataAccessException e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "error.notAuthorized"));
return "curricularPlansManagement";
} catch (FenixServiceException e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, e.getMessage()));
return "";
} catch (DomainException e) {
addErrorMessage(BundleUtil.getString(Bundle.DOMAIN_EXCEPTION, e.getKey(), e.getArgs()));
return "";
} catch (Exception e) {
this.addErrorMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "error.deletingDegreeCurricularPlan"));
return "curricularPlansManagement";
}
this.addInfoMessage(BundleUtil.getString(Bundle.SCIENTIFIC, "degreeCurricularPlan.deleted"));
return "curricularPlansManagement";
}
public String[] getSelectedGroupMembersToDelete() {
return selectedGroupMembersToDelete;
}
public void setSelectedGroupMembersToDelete(String[] selectedGroupMembersToDelete) {
this.selectedGroupMembersToDelete = selectedGroupMembersToDelete;
}
public String getDurationTypeName() {
if (durationTypeName == null && getDcp() != null) {
final AcademicPeriod duration = getDcp().getDegreeStructure().getAcademicPeriod();
return duration != null ? (durationTypeName = duration.getRepresentationInStringFormat()) : null;
}
return durationTypeName;
}
public void setDurationTypeName(String durationTypeName) {
this.durationTypeName = durationTypeName;
}
private AcademicPeriod getDuration() {
return getDurationTypeName().equals(NO_SELECTION) ? null : AcademicPeriod
.getAcademicPeriodFromString(getDurationTypeName());
}
public List<SelectItem> getDurationTypes() {
return (durationTypes == null) ? (durationTypes = readDurationTypes()) : durationTypes;
}
private List<SelectItem> readDurationTypes() {
final List<SelectItem> result = new ArrayList<SelectItem>();
final Set<AcademicPeriod> sortedPeriods = new TreeSet<>(Collections.reverseOrder());
sortedPeriods.addAll(AcademicPeriod.values());
for (final AcademicPeriod entry : sortedPeriods) {
if (!(entry instanceof AcademicYears)) {
//only year multiples are supported
continue;
}
result.add(new SelectItem(entry.getRepresentationInStringFormat(), BundleUtil.getString(Bundle.ENUMERATION,
entry.getName())));
}
result.add(0, new SelectItem(NO_SELECTION, BundleUtil.getString(Bundle.SCIENTIFIC, "choose")));
return result;
}
}