package com.intrbiz.bergamot.model;
import java.util.Calendar;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import com.intrbiz.bergamot.data.BergamotDB;
import com.intrbiz.bergamot.model.adapter.StatusesAdapter;
import com.intrbiz.bergamot.model.message.ContactMO;
import com.intrbiz.bergamot.model.message.EscalationMO;
import com.intrbiz.data.db.compiler.meta.Action;
import com.intrbiz.data.db.compiler.meta.SQLColumn;
import com.intrbiz.data.db.compiler.meta.SQLForeignKey;
import com.intrbiz.data.db.compiler.meta.SQLPrimaryKey;
import com.intrbiz.data.db.compiler.meta.SQLTable;
import com.intrbiz.data.db.compiler.meta.SQLVersion;
@SQLTable(schema = BergamotDB.class, name = "escalation", since = @SQLVersion({ 3, 22, 0 }))
public class Escalation extends BergamotObject<EscalationMO> implements Comparable<Escalation>
{
private static final long serialVersionUID = 1L;
@SQLColumn(index = 1, name = "notifications_id", since = @SQLVersion({ 3, 22, 0 }))
@SQLForeignKey(references = Notifications.class, on = "id", onDelete = Action.CASCADE, onUpdate = Action.RESTRICT, since = @SQLVersion({ 1, 0, 0 }))
@SQLPrimaryKey
private UUID notificationsId;
@SQLColumn(index = 2, name = "after", since = @SQLVersion({ 3, 22, 0 }))
@SQLPrimaryKey
private long after;
@SQLColumn(index = 3, name = "ignore", type = "TEXT[]", adapter = StatusesAdapter.class, since = @SQLVersion({ 3, 22, 0 }))
private List<Status> ignore = new LinkedList<Status>();
@SQLColumn(index = 4, name = "timeperiod_id", since = @SQLVersion({ 3, 22, 0 }))
@SQLForeignKey(references = TimePeriod.class, on = "id", onDelete = Action.RESTRICT, onUpdate = Action.RESTRICT, since = @SQLVersion({ 1, 0, 0 }))
private UUID timePeriodId;
/**
* Teams to notify
*/
@SQLColumn(index = 5, name = "team_ids", type = "UUID[]", since = @SQLVersion({ 3, 22, 0 }))
protected List<UUID> teamIds = new LinkedList<UUID>();
/**
* Contacts to notify
*/
@SQLColumn(index = 6, name = "contact_ids", type = "UUID[]", since = @SQLVersion({ 3, 22, 0 }))
protected List<UUID> contactIds = new LinkedList<UUID>();
/**
* Should we renotify the original contacts
*/
@SQLColumn(index = 7, name = "renotify", since = @SQLVersion({ 3, 36, 0 }))
protected boolean renotify = false;
public Escalation()
{
super();
}
public UUID getNotificationsId()
{
return notificationsId;
}
public void setNotificationsId(UUID notificationsId)
{
this.notificationsId = notificationsId;
}
public long getAfter()
{
return after;
}
public void setAfter(long after)
{
this.after = after;
}
public List<Status> getIgnore()
{
return ignore;
}
public void setIgnore(List<Status> ignore)
{
this.ignore = ignore;
}
public UUID getTimePeriodId()
{
return timePeriodId;
}
public void setTimePeriodId(UUID timePeriodId)
{
this.timePeriodId = timePeriodId;
}
public List<UUID> getTeamIds()
{
return teamIds;
}
public void setTeamIds(List<UUID> teamIds)
{
this.teamIds = teamIds;
}
public List<UUID> getContactIds()
{
return contactIds;
}
public void setContactIds(List<UUID> contactIds)
{
this.contactIds = contactIds;
}
public boolean isRenotify()
{
return renotify;
}
public void setRenotify(boolean renotify)
{
this.renotify = renotify;
}
public List<Team> getTeams()
{
List<Team> r = new LinkedList<Team>();
if (this.getTeamIds() != null)
{
try (BergamotDB db = BergamotDB.connect())
{
for (UUID id : this.getTeamIds())
{
r.add(db.getTeam(id));
}
}
}
return r;
}
public List<Contact> getContacts()
{
List<Contact> r = new LinkedList<Contact>();
if (this.getContactIds() != null)
{
try (BergamotDB db = BergamotDB.connect())
{
for (UUID id : this.getContactIds())
{
r.add(db.getContact(id));
}
}
}
return r;
}
public Set<Contact> getAllContacts()
{
Set<Contact> ret = new HashSet<Contact>();
ret.addAll(this.getContacts());
for (Team team : this.getTeams())
{
ret.addAll(team.getAllContacts());
}
return ret;
}
public TimePeriod getTimePeriod()
{
if (this.getTimePeriodId() == null) return null;
try (BergamotDB db = BergamotDB.connect())
{
return db.getTimePeriod(this.getTimePeriodId());
}
}
/**
* Is this escalation active for the given check state and a point in time
* @param status the status of the check
* @param time the time
* @return true if this escalation is active
*/
public boolean isActiveFor(Status status, Calendar time)
{
TimePeriod timePeriod = this.getTimePeriod();
return (!this.isStatusIgnored(status)) && (timePeriod == null ? true : timePeriod.isInTimeRange(time));
}
public boolean isStatusIgnored(Status status)
{
return this.ignore.stream().anyMatch((e) -> e == status);
}
/**
* Compute the list of contacts who should be notified
* @return a list of contact message objects
*/
public List<ContactMO> getContactsToNotify(Check<?,?> check, Status status, Calendar time)
{
final Notifications checkNotifications = check.getNotifications();
// compute the engines available
final Set<String> enabledEngines = checkNotifications.getEnginesEnabledAt(NotificationType.ALERT, status, time);
// compute the contacts to notify
return this.getAllContacts().stream()
.filter((contact) -> contact.getNotifications().isEnabledAt(NotificationType.ALERT, status, time))
.map((contact) -> {
ContactMO cmo = contact.toMOUnsafe();
cmo.setEngines(
contact.getNotifications().getEnginesEnabledAt(NotificationType.ALERT, status, time).stream()
.filter((engine) -> checkNotifications.isAllEnginesEnabled() || enabledEngines.contains(engine))
.collect(Collectors.toSet())
);
return cmo;
}).collect(Collectors.toList());
}
@Override
public EscalationMO toMO(Contact contact, EnumSet<com.intrbiz.bergamot.model.BergamotObject.MOFlag> options)
{
EscalationMO mo = new EscalationMO();
mo.setAfter(this.after);
mo.setRenotify(this.renotify);
mo.setIgnore(this.ignore.stream().map(Status::toString).collect(Collectors.toSet()));
TimePeriod timePeriod = this.getTimePeriod();
if (timePeriod != null)
{
if (contact == null || contact.hasPermission("read", timePeriod))
mo.setTimePeriod(timePeriod.toStubMO(contact));
}
mo.setContacts(this.getContacts().stream().filter((x) -> contact == null || contact.hasPermission("read", x)).map((x) -> x.toStubMO(contact)).collect(Collectors.toList()));
mo.setTeams(this.getTeams().stream().filter((x) -> contact == null || contact.hasPermission("read", x)).map((x) -> x.toStubMO(contact)).collect(Collectors.toList()));
return mo;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + (int) (after ^ (after >>> 32));
result = prime * result + ((notificationsId == null) ? 0 : notificationsId.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Escalation other = (Escalation) obj;
if (after != other.after) return false;
if (notificationsId == null)
{
if (other.notificationsId != null) return false;
}
else if (!notificationsId.equals(other.notificationsId)) return false;
return true;
}
@Override
public int compareTo(Escalation o)
{
return Long.compare(o.after, this.after);
}
}