/*
* @(#)PersonMissionAuthorization.java
*
* Copyright 2010 Instituto Superior Tecnico
* Founding Authors: Luis Cruz, Nuno Ochoa, Paulo Abrantes
*
* https://fenix-ashes.ist.utl.pt/
*
* This file is part of the Expenditure Tracking Module.
*
* The Expenditure Tracking Module 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.
*
* The Expenditure Tracking Module 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 the Expenditure Tracking Module. If not, see <http://www.gnu.org/licenses/>.
*
*/
package module.mission.domain;
import java.util.Comparator;
import java.util.Set;
import java.util.function.Predicate;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.security.Authenticate;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import jvstm.cps.ConsistencyPredicate;
import module.mission.domain.util.AuthorizationChain;
import module.organization.domain.Accountability;
import module.organization.domain.AccountabilityType;
import module.organization.domain.FunctionDelegation;
import module.organization.domain.Party;
import module.organization.domain.Person;
import module.organization.domain.Unit;
/**
*
* @author Luis Cruz
*
*/
public class PersonMissionAuthorization extends PersonMissionAuthorization_Base {
public static final Comparator<PersonMissionAuthorization> COMPARATOR_BY_PROCESS_NUMBER =
new Comparator<PersonMissionAuthorization>() {
@Override
public int compare(final PersonMissionAuthorization pma1, final PersonMissionAuthorization pma2) {
final MissionProcess missionProcess1 = pma1.getMissionProcess();
final MissionProcess missionProcess2 = pma2.getMissionProcess();
final int c = MissionProcess.COMPARATOR_BY_PROCESS_NUMBER.compare(missionProcess1, missionProcess2);
return c == 0 ? pma1.getExternalId().compareTo(pma2.getExternalId()) : c;
}
};
public static final Comparator<PersonMissionAuthorization> COMPARATOR_BY_DEPARTURE_DATE =
new Comparator<PersonMissionAuthorization>() {
@Override
public int compare(final PersonMissionAuthorization pma1, final PersonMissionAuthorization pma2) {
final MissionProcess missionProcess1 = pma1.getMissionProcess();
final MissionProcess missionProcess2 = pma2.getMissionProcess();
final Mission mission1 = missionProcess1.getMission();
final Mission mission2 = missionProcess2.getMission();
final DateTime departure1 = mission1.getDaparture();
final DateTime departure2 = mission2.getDaparture();
final int c = departure1.compareTo(departure2);
return c == 0 ? pma1.getExternalId().compareTo(pma2.getExternalId()) : c;
}
};
public PersonMissionAuthorization() {
super();
setMissionSystem(MissionSystem.getInstance());
}
public PersonMissionAuthorization(final Person subject, AuthorizationChain authorizationChain) {
this();
setSubject(subject);
final Unit unit = authorizationChain.getUnit();
setUnit(unit);
if (authorizationChain.getNext() != null) {
setNext(new PersonMissionAuthorization(subject, authorizationChain.getNext()));
}
}
public PersonMissionAuthorization(final Mission mission, final Person subject, final AuthorizationChain authorizationChain) {
this(subject, authorizationChain);
setMission(mission);
}
public void delete() {
if (hasNext()) {
getNext().delete();
}
setPrevious(null);
setSubject(null);
setUnit(null);
setMission(null);
setAuthority(null);
setMissionSystem(null);
deleteDomainObject();
}
public AccountabilityType getWorkingAccountabilityType() {
final DateTime departure = getMission().getDaparture();
final Person person = getSubject();
return person.getParentAccountabilityStream().filter(new Predicate<Accountability>() {
@Override
public boolean test(Accountability a) {
final LocalDate date = departure.toLocalDate();
if (a.isActive(date)) {
if (MissionSystem.REQUIRE_AUTHORIZATION_PREDICATE.test(a) && matchesUnit(a.getParent(), date)) {
return true;
}
}
return false;
}
}).map(a -> a.getAccountabilityType()).findAny().orElse(null);
}
private boolean matchesUnit(final Party party, final LocalDate date) {
if (party.isUnit()) {
final Unit unit = (Unit) party;
if (unit == getUnit()) {
return true;
}
final Set<AccountabilityType> typesSet =
MissionSystem.getInstance().getOrganizationalModel().getAccountabilityTypesSet();
return unit.getParentAccountabilityStream().anyMatch(
a -> a.isActive(date) && typesSet.contains(a.getAccountabilityType()) && matchesUnit(a.getParent(), date));
}
return false;
}
public boolean canAuthoriseParticipantActivity() {
final User user = Authenticate.getUser();
return user != null && canAuthoriseParticipantActivity(user.getPerson());
}
public boolean canAuthoriseParticipantActivity(final Person person) {
return canAuthoriseThisParticipantActivity(person) || canAuthoriseNextParticipantActivity(person);
}
private boolean canAuthoriseNextParticipantActivity(Person person) {
final PersonMissionAuthorization next = getNext();
return next != null && next.canAuthoriseParticipantActivity(person);
}
private boolean canAuthoriseThisParticipantActivity(final Person person) {
return getAuthority() == null && getDelegatedAuthority() == null
&& getUnit().hasChildAccountabilityIncludingAncestry(MissionSystem.AUTHORIZATION_PREDICATE, person);
}
public boolean isAvailableForAuthorization() {
return getAuthority() == null && getDelegatedAuthority() == null
&& (getNext() == null || getNext().isAvailableForAuthorization());
}
public boolean canUnAuthoriseParticipantActivity() {
final User user = Authenticate.getUser();
return user != null && canUnAuthoriseParticipantActivity(user.getPerson());
}
public boolean canUnAuthoriseParticipantActivity(final Person person) {
if (person == getSubject()) {
return false;
}
return (getAuthority() != null || getDelegatedAuthority() != null)
&& canUnAuthorise(person, MissionSystem.AUTHORIZATION_PREDICATE)
&& ((getNext() == null) || (getNext().getAuthority() == null && getNext().getDelegatedAuthority() == null));
}
private boolean canUnAuthorise(final Person person, final Predicate<Accountability> predicate) {
final Unit unitForAuthorizationCheck =
getDelegatedAuthority() != null && getPrevious() != null ? getPrevious().getUnit() : getUnit();
return unitForAuthorizationCheck.hasChildAccountabilityIncludingAncestry(predicate, person)
|| (getNext() != null && getNext().canUnAuthorise(person, predicate));
}
public boolean canUnAuthoriseSomeParticipantActivity(final Person person) {
return canUnAuthoriseParticipantActivity(person)
|| (getNext() != null && getNext().canUnAuthoriseSomeParticipantActivity(person));
}
@Override
public void setAuthority(final Person authority) {
super.setAuthority(authority);
final DateTime authorizationDateTime = authority == null ? null : new DateTime();
setAuthorizationDateTime(authorizationDateTime);
if (getNext() != null) {
getNext().setDelegatedAuthority(authority);
}
}
private void setDelegatedAuthority(final Person authority) {
if (authority == null) {
setDelegatedAuthority((FunctionDelegation) null);
return;
}
authority.getParentAccountabilityStream().filter(a -> a.isActiveNow() && MissionSystem.AUTHORIZATION_PREDICATE.test(a))
.map(a -> a.getFunctionDelegationDelegator()).filter(fd -> fd != null)
.filter(fd -> fd.getAccountabilityDelegator().getParent() == getUnit()).findAny()
.ifPresent(fd -> setDelegatedAuthority(fd));
}
public boolean hasAnyAuthorization() {
return (getAuthorizationDateTime() != null && (getAuthority() != null || getDelegatedAuthority() != null))
|| (getNext() != null && getNext().hasAnyAuthorization());
}
public boolean isAuthorized() {
return (getNext() == null && (getAuthority() != null || getDelegatedAuthority() != null)) || (getNext() != null && getNext().isAuthorized());
}
public boolean isPreAuthorized() {
return getNext() == null || getNext().getNext() == null || ((getAuthority() != null || getDelegatedAuthority() != null) && getNext().isPreAuthorized());
}
public int getChainSize() {
return getNext() != null ? getNext().getChainSize() + 1 : 1;
}
public Mission getAssociatedMission() {
final Mission mission = getMission();
return mission != null || getPrevious() == null ? mission : getPrevious().getAssociatedMission();
}
public void clearAuthorities() {
if (hasNext()) {
getNext().clearAuthorities();
}
setAuthority(null);
setDelegatedAuthority((FunctionDelegation) null);
}
public MissionProcess getMissionProcess() {
return getMission() != null ? getMission().getMissionProcess() : (getPrevious() != null ? getPrevious().getMissionProcess() : null);
}
public boolean isProcessTakenByOtherUser() {
final MissionProcess missionProcess = getMissionProcess();
return missionProcess.getCurrentOwner() != null && !missionProcess.isTakenByCurrentUser();
}
public boolean isUnitObserver(final User user) {
final Unit unit = getUnit();
final pt.ist.expenditureTrackingSystem.domain.organization.Unit expenditureUnit = unit.getExpenditureUnit();
if (expenditureUnit != null && expenditureUnit.isUnitObserver(user)) {
return true;
}
return hasNext() && getNext().isUnitObserver(user);
}
@ConsistencyPredicate
public boolean checkIsConnectedToList() {
return ((getMission() != null && getPrevious() == null) || (getMission() == null && getPrevious() != null));
}
@Deprecated
public boolean hasAuthorizationDateTime() {
return getAuthorizationDateTime() != null;
}
@Deprecated
public boolean hasMissionSystem() {
return getMissionSystem() != null;
}
@Deprecated
public boolean hasSubject() {
return getSubject() != null;
}
@Deprecated
public boolean hasMission() {
return getMission() != null;
}
@Deprecated
public boolean hasAuthority() {
return getAuthority() != null;
}
@Deprecated
public boolean hasDelegatedAuthority() {
return getDelegatedAuthority() != null;
}
@Deprecated
public boolean hasUnit() {
return getUnit() != null;
}
@Deprecated
public boolean hasPrevious() {
return getPrevious() != null;
}
@Deprecated
public boolean hasNext() {
return getNext() != null;
}
}