package de.flower.rmt.model.db.entity.event;
import de.flower.rmt.model.db.entity.AbstractClubRelatedEntity;
import de.flower.rmt.model.db.entity.Club;
import de.flower.rmt.model.db.entity.Invitation;
import de.flower.rmt.model.db.entity.Opponent;
import de.flower.rmt.model.db.entity.Team;
import de.flower.rmt.model.db.entity.User;
import de.flower.rmt.model.db.entity.Venue;
import de.flower.rmt.model.db.type.EventType;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.NotBlank;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author flowerrrr
*/
@Entity
@Table(name = "event")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name = "eventType",
discriminatorType = DiscriminatorType.STRING
)
@DiscriminatorValue("Event")
public class Event extends AbstractClubRelatedEntity {
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@Index(name = "ix_team")
private Team team;
/**
* Can be null. Sometimes events are created before it is clear where they are held.
*/
@ManyToOne(fetch = FetchType.LAZY)
private Venue venue;
/**
* Two separate fields to make form validation easier.
* Modelled as java.util.Date instead of joda-date cause this makes handling the field
* in wicket forms much easier. Also required to have validation constraint for datepicker.
* Time part of this field is always midnight 00:00:00.
*/
@NotNull
@Transient
private Date date;
/**
* Only the time part of the meeting time.
*/
@NotNull
@Transient
private LocalTime time;
/**
* Will be translated to dateTimeEnd by service layer when saved.
*/
// @NotNull
@Transient
private LocalTime timeEnd;
/**
* Derived field. Mostly used when searching for event by date and ordering by date.
* Field is updated whenever #setDate() or #setTime() is called.
*/
@Column
@NotNull
@Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
@Index(name = "ix_datetime")
private DateTime dateTime;
/**
* Optional field. Needed for iCalender objects
*/
@Column
@Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
private DateTime dateTimeEnd;
@Column
@NotBlank
@Size(max = 70)
private String summary;
@Column
@Size(max = 255)
private String comment;
@NotNull
@Column
@Index(name = "ix_invitationsent")
private Boolean invitationSent;
@Column
@Index(name = "ix_canceled")
private Boolean canceled = false;
@ManyToOne
@NotNull
private User createdBy;
@OneToMany(mappedBy = "event", cascade = CascadeType.REMOVE)
private List<Invitation> invitations = new ArrayList<Invitation>();
/**
* Defined here to be able to eager fetch this association with query dsl.
* Can be null. Sometimes events are created without knowing who the opponent will be.
*/
@ManyToOne(fetch = FetchType.LAZY)
private Opponent opponent;
protected Event() {
}
public Event(Club club) {
super(club);
this.invitationSent = false;
}
public Event(Team team) {
this(team.getClub());
this.team = team;
}
public void copyFrom(final Event event) {
setTeam(event.getTeam());
setDateTime(event.getDateTime());
setDateTimeEnd(event.getDateTimeEnd());
setVenue(event.getVenue());
_setOpponent(_getOpponent());
setSummary(event.getSummary());
setComment(event.getComment());
}
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
public Venue getVenue() {
return venue;
}
public void setVenue(Venue venue) {
this.venue = venue;
}
// **************************************************
// Date functions
// **************************************************
@Deprecated // only used for wicket form
public Date getDate() {
// must return raw value, otherwise validator would fail.
return date;
}
/**
* Setter used by datepicker field.
*/
@Deprecated // use #setDateTime if called from user code.
public void setDate(Date date) {
// normalize to midnight
this.date = (date == null) ? null : new LocalDate(date).toDate();
updateDateTime(this.date);
}
@Deprecated // only used for wicket form
public LocalTime getTime() {
// must return raw value, otherwise validator would fail.
return time;
}
/**
* Setter for wicket form component
*/
@Deprecated // use #setDateTime if called from user code.
public void setTime(LocalTime time) {
this.time = time;
updateDateTime(time);
}
/**
* Returns full date of event. date + time
*
* @return
*/
public DateTime getDateTime() {
return dateTime;
}
public void setDateTime(final DateTime dateTime) {
this.dateTime = dateTime;
if (dateTime == null) {
this.date = null;
this.time = null;
} else {
this.date = dateTime.toLocalDate().toDate();
this.time = dateTime.toLocalTime();
}
}
/**
* Used for wicket date fields.
*
* @return
*/
public Date getDateTimeAsDate() {
return (dateTime == null) ? null : dateTime.toDate();
}
private void updateDateTime(Date date) {
if (date == null) {
dateTime = null;
} else {
if (time == null) {
dateTime = new DateTime(date);
} else {
dateTime = new DateTime(date).withFields(time);
}
}
}
private void updateDateTime(LocalTime time) {
if (time == null) {
dateTime = null;
} else {
if (date == null) {
dateTime = new DateTime(0).withFields(time);
} else {
dateTime = new DateTime(date).withFields(time);
}
}
}
/**
* called before object is used in edit form.
*/
public void initTransientFields() {
setDateTime(getDateTime());
setDateTimeEnd(getDateTimeEnd());
}
public DateTime getDateTimeEnd() {
if (dateTimeEnd == null & getDateTime() != null && getEventType() != null) {
// guess duration of event.
return getDateTime().plusMinutes(getEventType().getMeetBeforeKickOffMinutes() + getEventType().getDurationMinutes());
} else {
return dateTimeEnd;
}
}
public void setDateTimeEnd(final DateTime dateTimeEnd) {
this.dateTimeEnd = dateTimeEnd;
if (this.dateTimeEnd == null) {
this.timeEnd = null;
} else {
this.timeEnd = dateTimeEnd.toLocalTime();
}
}
public LocalTime getTimeEnd() {
return timeEnd;
}
public void setTimeEnd(final LocalTime timeEnd) {
this.timeEnd = timeEnd;
}
// **************************************************
// End Date functions
// **************************************************
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public boolean isInvitationSent() {
return invitationSent;
}
public void setInvitationSent(final Boolean invitationSent) {
this.invitationSent = invitationSent;
}
/**
* association might not be initialized after loading an event when query is build
* using Event_.invitations. This variable can have different values depending
* on startup behavior of app (based on Match, Tournament or Training).
*
* @return
*/
@Deprecated
public List<Invitation> getInvitations() {
return invitations;
}
public User getCreatedBy() {
return createdBy;
}
public boolean isCanceled() {
// database field might be null as column was added later
return canceled == null ? false : canceled;
}
public void setCanceled(final boolean canceled) {
this.canceled = canceled;
}
public void setCreatedBy(final User createdBy) {
this.createdBy = createdBy;
}
public EventType getEventType() {
return EventType.from(this);
}
@Deprecated // should only be called from Match instances
protected Opponent _getOpponent() {
return opponent;
}
@Deprecated // should only be called from Match instances
protected void _setOpponent(final Opponent opponent) {
this.opponent = opponent;
}
@Override
public String toString() {
return "Event{" +
"id=" + getId() +
", date=" + date +
", time=" + time +
", summary='" + summary + '\'' +
'}';
}
}