/*
* Copyright 2012 SURFnet bv, The Netherlands
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package teams.domain;
import static javax.persistence.CascadeType.ALL;
import static javax.persistence.FetchType.EAGER;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Proxy;
import org.hibernate.annotations.SortNatural;
import org.springframework.util.CollectionUtils;
import teams.util.InvitationGenerator;
@SuppressWarnings("serial")
@Entity
@Table(name = "invitations")
@Proxy(lazy = false)
public class Invitation extends DomainObject {
private static final long TWO_WEEKS = 14L * 24L * 60L * 60L * 1000L;
@Column(name = "group_id", nullable = false)
private String teamId;
@Column(name = "mailaddress", nullable = false)
private String email;
@Column(nullable = false)
private long timestamp;
@Column(name = "invitation_uiid", nullable = false)
private String invitationHash;
@Column(name = "denied")
private boolean declined;
@Column(name = "accepted")
private boolean accepted;
@OneToMany(cascade = ALL, fetch = EAGER, mappedBy = "invitation")
@SortNatural
private List<InvitationMessage> invitationMessages;
@Enumerated(EnumType.STRING)
@Column(name = "intended_role", nullable = true)
private Role intendedRole;
@Enumerated(EnumType.STRING)
private Language language = Language.English;
/**
* Constructor Hibernate needs when fetching results from the db.
* Do not use to create new Invitations.
*/
public Invitation() {
this(null, null);
}
/**
* Constructor with the most common fields
*
* @param email address of the person to invite
* @param teamId id of the team the person will join
*/
public Invitation(String email, String teamId) {
this.setEmail(email);
this.setTeamId(teamId);
this.setInvitationHash();
this.setTimestamp(new Date().getTime());
this.setInvitationMessages(new ArrayList<>());
}
/**
* @param teamId the teamId to set
*/
public void setTeamId(String teamId) {
this.teamId = teamId;
}
/**
* @return the teamId
*/
public String getTeamId() {
return teamId;
}
/**
* @param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
/**
* @return the email
*/
public String getEmail() {
return email;
}
/**
* @return timestamp when the invitation was last updates
*/
public long getTimestamp() {
return timestamp;
}
/**
* @param timestamp to indicate when the invitation was last updated
*/
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
/**
* @return unique hash to identify the invitation
*/
public String getInvitationHash() {
return invitationHash;
}
/**
* sets an md5 hash created from a UUID generated from the email address
*/
void setInvitationHash() {
this.invitationHash = InvitationGenerator.generateHash();
}
/**
* @return {@literal true} if the invitee has declined the invitation
*/
public boolean isDeclined() {
return declined;
}
/**
* @param declined indicator if the invitation is denied
*/
public void setDeclined(boolean declined) {
this.declined = declined;
}
/**
* @return {@literal true} if the invitee has accepted the invitation
*/
public boolean isAccepted() {
return accepted;
}
/**
* @param accepted indicator if the invitation is denied
*/
public void setAccepted(boolean accepted) {
this.accepted = accepted;
}
/**
* @return List of {@link InvitationMessage}'s
*/
public List<InvitationMessage> getInvitationMessages() {
return invitationMessages;
}
private void setInvitationMessages(List<InvitationMessage> invitationMessages) {
this.invitationMessages = invitationMessages;
}
public Language getLanguage() {
return language;
}
public void setLanguage(Language language) {
this.language = language;
}
/**
* Adds one {@link InvitationMessage} to this Invitation
*
* @param invitationMessage {@link InvitationMessage} to add
*/
public void addInvitationMessage(InvitationMessage invitationMessage) {
invitationMessage.setInvitation(this);
this.invitationMessages.add(invitationMessage);
}
public Optional<InvitationMessage> getLatestInvitationMessage() {
if (CollectionUtils.isEmpty(invitationMessages)) {
return Optional.empty();
}
return Optional.of(invitationMessages.get(invitationMessages.size() - 1));
}
public List<InvitationMessage> getInvitationMessagesReversed() {
List<InvitationMessage> copy = new ArrayList<>(invitationMessages.size());
copy.addAll(invitationMessages);
Collections.reverse(copy);
return copy;
}
public long getExpireTime() {
return timestamp + TWO_WEEKS;
}
/**
* @return the {@link Role} the invitee should get within the team. Defaults to {@link Role#Member}
*/
public Role getIntendedRole() {
if (intendedRole == null) {
intendedRole = Role.Member;
}
return intendedRole;
}
/**
* Setting a role other than {@link Role#Member} can give the invitee more privileges automatically
*
* @param intendedRole the {@link Role} the invitee should get within the team. Can be {@literal null}
*/
public void setIntendedRole(Role intendedRole) {
this.intendedRole = intendedRole;
}
public void accept() {
setAccepted(true);
}
public void decline() {
setDeclined(true);
}
}