/* Copyright (c) 2011 Danish Maritime Authority
*
* This library 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.
*
* This library 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 General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
package dk.dma.ais.abnormal.event.db.domain;
import com.google.common.collect.ImmutableSet;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.validator.constraints.NotBlank;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.stream.Collectors;
/**
* This abstract class is the common class of all Events. An event describes some sort of abnormal behaviour
* detected among moving vessels in the maritime domain.
*
* An Event is also related to at least one vessel. Some event types can be related to further vessels or to
* other Events.
*/
@Table(
indexes = {
@Index(name="INDEX_EVENT_STARTTIME", columnList = "startTime"),
@Index(name="INDEX_EVENT_ENDTIME", columnList = "endTime"),
@Index(name="INDEX_EVENT_SUPPRESSED", columnList = "suppressed")
}
)
@Entity
public abstract class Event {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
/** State of the event. */
@NotNull
@Enumerated(EnumType.STRING)
private State state = State.ONGOING;
/** Time on which the event started. */
@NotNull
private LocalDateTime startTime;
/** Time on which the event ended. */
private LocalDateTime endTime;
/** True if this event is suppressed by an operator who concludes that this isn't an event */
private boolean suppressed = false;
// TODO create index on event_behaviour(event_id);
/** The behaviour observed in connection with this event */
@OneToMany(cascade = CascadeType.ALL)
@Fetch(FetchMode.JOIN)
private Set<Behaviour> behaviours;
/** A title of the event in English language. */
@NotBlank
private String title;
/** A textual description of the event in English language. */
private String description;
protected Event() {
this.behaviours = new HashSet<>();
}
public long getId() {
return id;
}
public String getEventType() {
return this.getClass().getSimpleName();
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public boolean isSuppressed() {
return suppressed;
}
public void setSuppressed(boolean suppressed) {
this.suppressed = suppressed;
}
public Behaviour getBehaviour(int mmsi) {
Behaviour behaviour = null;
try {
behaviour = behaviours.stream().filter(b -> b.getVessel().getMmsi() == mmsi).findFirst().get();
} catch (NoSuchElementException e) {
}
return behaviour;
}
public Set<Behaviour> getBehaviours() {
return ImmutableSet.copyOf(behaviours);
}
public void addBehaviour(Behaviour behaviour) {
this.behaviours.add(behaviour);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<Integer> involvedMmsis() {
return behaviours.stream().map(b -> b.getVessel().getMmsi()).distinct().collect(Collectors.toSet());
}
public Behaviour primaryBehaviour() {
Behaviour primaryBehaviour = null;
try {
primaryBehaviour = behaviours.stream().filter(b -> b.isPrimary()).findFirst().get();
} catch (NoSuchElementException e) {
}
return primaryBehaviour;
}
public Behaviour arbitraryNonPrimaryBehaviour() {
Behaviour arbitraryNonPrimaryBehaviour = null;
try {
arbitraryNonPrimaryBehaviour = behaviours.stream().filter(b -> !(b.isPrimary())).findFirst().get();
} catch (NoSuchElementException e) {
}
return arbitraryNonPrimaryBehaviour;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Event{");
sb.append("id=").append(id);
sb.append(", state=").append(state);
sb.append(", startTime=").append(startTime);
sb.append(", endTime=").append(endTime);
sb.append(", suppressed=").append(suppressed);
sb.append(", behaviours=").append(behaviours);
sb.append(", title='").append(title).append('\'');
sb.append(", description='").append(description).append('\'');
sb.append('}');
return sb.toString();
}
public enum State {
ONGOING,
PAST
}
}