/**
* 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.domain.phd.candidacy.feedbackRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.fenixedu.academic.domain.ExecutionYear;
import org.fenixedu.academic.domain.Person;
import org.fenixedu.academic.domain.caseHandling.Activity;
import org.fenixedu.academic.domain.caseHandling.PreConditionNotValidException;
import org.fenixedu.academic.domain.caseHandling.StartActivity;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.domain.person.RoleType;
import org.fenixedu.academic.domain.phd.InternalPhdParticipant;
import org.fenixedu.academic.domain.phd.PhdIndividualProgramDocumentType;
import org.fenixedu.academic.domain.phd.PhdIndividualProgramProcess;
import org.fenixedu.academic.domain.phd.PhdParticipant;
import org.fenixedu.academic.domain.phd.PhdParticipantBean;
import org.fenixedu.academic.domain.phd.PhdProgramCandidacyProcessState;
import org.fenixedu.academic.domain.phd.PhdProgramDocumentUploadBean;
import org.fenixedu.academic.domain.phd.PhdProgramProcessDocument;
import org.fenixedu.academic.domain.phd.access.ExternalAccessPhdActivity;
import org.fenixedu.academic.domain.phd.access.PhdExternalOperationBean;
import org.fenixedu.academic.domain.phd.access.PhdProcessAccessType;
import org.fenixedu.academic.domain.phd.alert.AlertService;
import org.fenixedu.academic.domain.phd.alert.AlertService.AlertMessage;
import org.fenixedu.academic.domain.util.email.Message;
import org.fenixedu.academic.domain.util.email.SystemSender;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.academic.util.phd.PhdProperties;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.joda.time.DateTime;
public class PhdCandidacyFeedbackRequestProcess extends PhdCandidacyFeedbackRequestProcess_Base {
private PhdCandidacyFeedbackRequestProcess() {
super();
}
@Override
public List<Activity> getActivities() {
return activities;
}
@Override
protected PhdIndividualProgramProcess getIndividualProgramProcess() {
return getCandidacyProcess().getIndividualProgramProcess();
}
@Override
protected Person getPerson() {
return getIndividualProgramProcess().getPerson();
}
@Override
public boolean canExecuteActivity(User userView) {
return true;
}
@Override
public boolean isAllowedToManageProcess(User userView) {
return true;
}
@Override
public String getDisplayName() {
return BundleUtil.getString(Bundle.PHD, getClass().getSimpleName());
}
@Override
public PhdCandidacyFeedbackStateType getActiveState() {
return (PhdCandidacyFeedbackStateType) super.getActiveState();
}
protected void createState(final PhdCandidacyFeedbackStateType type, final Person person, final String remarks,
final DateTime stateDate) {
new PhdCandidacyFeedbackState(this, type, person, remarks, stateDate);
}
protected PhdCandidacyFeedbackRequestElement getCandidacyFeedbackRequestElement(final PhdParticipant participant) {
for (final PhdCandidacyFeedbackRequestElement element : getElementsSet()) {
if (element.getParticipant() == participant) {
return element;
}
}
return null;
}
public Set<PhdIndividualProgramDocumentType> getSortedSharedDocumentTypes() {
return getSharedDocuments().getSortedTypes();
}
/*
* Documents used by elements to analize candidacy and upload candidacy
*/
public Set<PhdProgramProcessDocument> getSharedDocumentsContent() {
final Set<PhdProgramProcessDocument> result = new HashSet<PhdProgramProcessDocument>();
for (final PhdIndividualProgramDocumentType type : getSortedSharedDocumentTypes()) {
if (type.isVersioned()) {
final PhdProgramProcessDocument document = getCandidacyProcess().getLatestDocumentVersionFor(type);
if (document != null) {
result.add(document);
}
}
}
return result;
}
public Set<PhdProgramProcessDocument> getSubmittedCandidacyFeedbackDocuments() {
final Set<PhdProgramProcessDocument> result = new HashSet<PhdProgramProcessDocument>();
for (final PhdCandidacyFeedbackRequestElement element : getElementsSet()) {
final PhdCandidacyFeedbackRequestDocument document = element.getLastFeedbackDocument();
if (document != null) {
result.add(document);
}
}
return result;
}
public boolean canUploadDocuments() {
/*
* CORRECT THIS METHOD
*/
// return
// getCandidacyProcess().isInState(PhdProgramCandidacyProcessState.PENDING_FOR_COORDINATOR_OPINION);
return true;
}
private void notifyCoordinationOfCandidacyFeedback(final PhdCandidacyFeedbackRequestElement element) {
AlertService.alertParticipants(getIndividualProgramProcess(), AlertMessage
.create("message.phd.candidacy.feedback.coordinator.notification.subject"), AlertMessage.create(
"message.phd.candidacy.feedback.coordinator.notification.body", element.getNameWithTitle(),
getIndividualProgramProcess().getPerson().getName()), getOrCreateParticipantsToNofify());
}
private PhdParticipant[] getOrCreateParticipantsToNofify() {
final PhdIndividualProgramProcess mainProcess = getIndividualProgramProcess();
final List<PhdParticipant> result = new ArrayList<PhdParticipant>();
for (final Person person : mainProcess.getCoordinatorsFor(ExecutionYear.readCurrentExecutionYear())) {
final PhdParticipant participant = mainProcess.getParticipant(person);
if (participant == null) {
result.add(PhdParticipant.getUpdatedOrCreate(mainProcess, new PhdParticipantBean().setInternalParticipant(person)));
} else if (participant.getCandidacyFeedbackRequestElementsSet().isEmpty()) {
result.add(participant);
}
}
return result.toArray(new PhdParticipant[result.size()]);
}
public boolean hasElement(final Person person) {
for (final PhdCandidacyFeedbackRequestElement element : getElementsSet()) {
if (element.isFor(person)) {
return true;
}
}
return false;
}
public PhdCandidacyFeedbackRequestElement getElement(final Person person) {
for (final PhdCandidacyFeedbackRequestElement element : getElementsSet()) {
if (element.isFor(person)) {
return element;
}
}
return null;
}
/*
* ACTIVITIES
*/
static abstract private class PhdActivity extends Activity<PhdCandidacyFeedbackRequestProcess> {
@Override
final public void checkPreConditions(final PhdCandidacyFeedbackRequestProcess process, final User userView) {
processPreConditions(process, userView);
activityPreConditions(process, userView);
}
protected void processPreConditions(final PhdCandidacyFeedbackRequestProcess process, final User userView) {
if (!process.getCandidacyProcess().isInState(PhdProgramCandidacyProcessState.PENDING_FOR_COORDINATOR_OPINION)) {
throw new PreConditionNotValidException(
"error.PhdCandidacyFeedbackRequestProcess.candidacy.process.is.not.pending.for.coordinator.opinion");
}
}
abstract protected void activityPreConditions(final PhdCandidacyFeedbackRequestProcess process, final User userView);
}
@StartActivity
static public class CreateCandidacy extends PhdActivity {
@Override
protected void processPreConditions(PhdCandidacyFeedbackRequestProcess process, User userView) {
// Auto-generated method stub
}
@Override
protected void activityPreConditions(PhdCandidacyFeedbackRequestProcess noProcess, User userView) {
}
@Override
protected PhdCandidacyFeedbackRequestProcess executeActivity(PhdCandidacyFeedbackRequestProcess noProcess, User userView,
Object object) {
final PhdCandidacyFeedbackRequestProcessBean bean = (PhdCandidacyFeedbackRequestProcessBean) object;
final PhdCandidacyFeedbackRequestProcess process = new PhdCandidacyFeedbackRequestProcess();
process.setSharedDocuments(new PhdCandidacySharedDocumentsList(bean.getSharedDocuments()));
process.setCandidacyProcess(bean.getCandidacyProcess());
process.createState(PhdCandidacyFeedbackStateType.NEW, userView.getPerson(), null, new DateTime());
return process;
}
}
static public class EditSharedDocumentTypes extends PhdActivity {
@Override
protected void activityPreConditions(PhdCandidacyFeedbackRequestProcess process, User userView) {
if (!process.getIndividualProgramProcess().isCoordinatorForPhdProgram(userView.getPerson())) {
throw new PreConditionNotValidException();
}
}
@Override
protected PhdCandidacyFeedbackRequestProcess executeActivity(PhdCandidacyFeedbackRequestProcess process, User userView,
Object object) {
final PhdCandidacyFeedbackRequestProcessBean bean = (PhdCandidacyFeedbackRequestProcessBean) object;
process.setSharedDocuments(new PhdCandidacySharedDocumentsList(bean.getSharedDocuments()));
return process;
}
}
static public class AddPhdCandidacyFeedbackRequestElements extends PhdActivity {
@Override
protected void activityPreConditions(PhdCandidacyFeedbackRequestProcess process, User userView) {
if (!process.getIndividualProgramProcess().isCoordinatorForPhdProgram(userView.getPerson())) {
throw new PreConditionNotValidException();
}
}
@Override
protected PhdCandidacyFeedbackRequestProcess executeActivity(PhdCandidacyFeedbackRequestProcess process, User userView,
Object object) {
final PhdCandidacyFeedbackRequestElementBean bean = (PhdCandidacyFeedbackRequestElementBean) object;
if (bean.isExistingElement()) {
if (!bean.hasAnyParticipants()) {
throw new DomainException("error.PhdCandidacyFeedbackRequestProcess.must.add.participants");
}
for (final PhdParticipant participant : bean.getParticipants()) {
final PhdCandidacyFeedbackRequestElement element =
PhdCandidacyFeedbackRequestElement.create(process, participant, bean);
addAccessPermissionsIfNecessary(element);
notifyElement(process, element, bean);
}
} else {
final PhdCandidacyFeedbackRequestElement element = PhdCandidacyFeedbackRequestElement.create(process, bean);
addAccessPermissionsIfNecessary(element);
notifyElement(process, element, bean);
}
return process;
}
private void addAccessPermissionsIfNecessary(final PhdCandidacyFeedbackRequestElement element) {
if (!element.getParticipant().isInternal()) {
element.getParticipant().addAccessType(PhdProcessAccessType.CANDIDACY_FEEDBACK_DOCUMENTS_DOWNLOAD,
PhdProcessAccessType.CANDIDACY_FEEDBACK_UPLOAD);
}
}
private void notifyElement(final PhdCandidacyFeedbackRequestProcess process,
final PhdCandidacyFeedbackRequestElement element, final PhdCandidacyFeedbackRequestElementBean bean) {
final String body =
bean.getMailBody() + "\n\n"
+ getAccessInformation(process.getIndividualProgramProcess(), element.getParticipant()) + "\n\n";
email(element.getEmail(), bean.getMailSubject(), body);
}
private String getAccessInformation(PhdIndividualProgramProcess process, PhdParticipant participant) {
if (!participant.isInternal()) {
return AlertMessage.get("message.phd.external.access", PhdProperties.getPhdExternalAccessLink(),
participant.getAccessHashCode(), participant.getPassword());
} else {
final Person person = ((InternalPhdParticipant) participant).getPerson();
if (process.isCoordinatorForPhdProgram(person)) {
return AlertMessage.get("message.phd.candidacy.feedback.coordinator.access");
} else if (process.isGuiderOrAssistentGuider(person) || RoleType.TEACHER.isMember(person.getUser())) {
return AlertMessage.get("message.phd.candidacy.feedback.teacher.access");
}
}
throw new DomainException("error.PhdThesisProcess.unexpected.participant.type");
}
private void email(String email, String subject, String body) {
final SystemSender sender = Bennu.getInstance().getSystemSender();
new Message(sender, sender.getConcreteReplyTos(), null, null, null, subject, body, Collections.singleton(email));
}
}
static public class DeleteCandidacyFeedbackRequestElement extends PhdActivity {
@Override
protected void activityPreConditions(PhdCandidacyFeedbackRequestProcess process, User userView) {
if (!process.getIndividualProgramProcess().isCoordinatorForPhdProgram(userView.getPerson())) {
throw new PreConditionNotValidException();
}
}
@Override
protected PhdCandidacyFeedbackRequestProcess executeActivity(PhdCandidacyFeedbackRequestProcess process, User userView,
Object object) {
((PhdCandidacyFeedbackRequestElement) object).delete();
return process;
}
}
static public class UploadCandidacyFeedback extends PhdActivity {
@Override
protected void activityPreConditions(PhdCandidacyFeedbackRequestProcess process, User userView) {
if (!process.hasElement(userView.getPerson())) {
throw new PreConditionNotValidException();
}
}
@Override
protected PhdCandidacyFeedbackRequestProcess executeActivity(PhdCandidacyFeedbackRequestProcess process, User userView,
Object object) {
final PhdProgramDocumentUploadBean bean = (PhdProgramDocumentUploadBean) object;
if (bean.hasAnyInformation()) {
final PhdCandidacyFeedbackRequestElement element = process.getElement(userView.getPerson());
new PhdCandidacyFeedbackRequestDocument(element, bean.getRemarks(), bean.getFileContent(), bean.getFilename(),
null);
process.notifyCoordinationOfCandidacyFeedback(element);
}
return process;
}
}
static public class DownloadCandidacyFeedbackDocuments extends ExternalAccessPhdActivity<PhdCandidacyFeedbackRequestProcess> {
@Override
public void checkPreConditions(PhdCandidacyFeedbackRequestProcess process, User userView) {
if (!process.getCandidacyProcess().isInState(PhdProgramCandidacyProcessState.PENDING_FOR_COORDINATOR_OPINION)) {
throw new PreConditionNotValidException(
"error.PhdCandidacyFeedbackRequestProcess.candidacy.process.is.not.pending.for.coordinator.opinion");
}
}
@Override
protected PhdCandidacyFeedbackRequestProcess internalExecuteActivity(PhdCandidacyFeedbackRequestProcess process,
User userView, PhdExternalOperationBean bean) {
// Auto-generated method stub
return process;
}
}
static public class ExternalUploadCandidacyFeedback extends ExternalAccessPhdActivity<PhdCandidacyFeedbackRequestProcess> {
@Override
public void checkPreConditions(PhdCandidacyFeedbackRequestProcess process, User userView) {
if (!process.getCandidacyProcess().isInState(PhdProgramCandidacyProcessState.PENDING_FOR_COORDINATOR_OPINION)) {
throw new PreConditionNotValidException(
"error.PhdCandidacyFeedbackRequestProcess.candidacy.process.is.not.pending.for.coordinator.opinion");
}
}
@Override
protected PhdCandidacyFeedbackRequestProcess internalExecuteActivity(PhdCandidacyFeedbackRequestProcess process,
User userView, PhdExternalOperationBean bean) {
if (bean.getDocumentBean().hasAnyInformation()) {
final PhdCandidacyFeedbackRequestElement element =
process.getCandidacyFeedbackRequestElement(bean.getParticipant());
final PhdProgramDocumentUploadBean documentBean = bean.getDocumentBean();
new PhdCandidacyFeedbackRequestDocument(element, documentBean.getRemarks(), documentBean.getFileContent(),
documentBean.getFilename(), null);
process.notifyCoordinationOfCandidacyFeedback(element);
}
return process;
}
}
static private List<Activity> activities = new ArrayList<Activity>();
static {
activities.add(new EditSharedDocumentTypes());
activities.add(new AddPhdCandidacyFeedbackRequestElements());
activities.add(new DeleteCandidacyFeedbackRequestElement());
activities.add(new UploadCandidacyFeedback());
activities.add(new DownloadCandidacyFeedbackDocuments());
activities.add(new ExternalUploadCandidacyFeedback());
}
@Override
@Deprecated
public java.util.Set<org.fenixedu.academic.domain.phd.candidacy.feedbackRequest.PhdCandidacyFeedbackState> getStates() {
return getStatesSet();
}
@Override
public boolean hasAnyStates() {
return !getStatesSet().isEmpty();
}
}