/**
* Yobi, Project Hosting SW
*
* Copyright 2013 NAVER Corp.
* http://yobi.io
*
* @author Yi EungJun
*
* 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 models;
import models.enumeration.EventType;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import play.Configuration;
import play.db.ebean.Model;
import javax.persistence.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
@Entity
public class IssueEvent extends Model implements TimelineItem {
private static final long serialVersionUID = 4029013291153199185L;
@Id
public Long id;
public Date created;
public String senderLoginId;
public String senderEmail;
@ManyToOne
public Issue issue;
@Enumerated(EnumType.STRING)
public EventType eventType;
public String oldValue;
public String newValue;
private static final int DRAFT_TIME_IN_MILLIS = Configuration.root()
.getMilliseconds("application.issue-event.draft-time", 30 * 1000L).intValue();
public static final Finder<Long, IssueEvent> find = new Finder<>(Long.class,
IssueEvent.class);
/**
* Adds {@code event}.
*
* If the last event is not older than {@link #DRAFT_TIME_IN_MILLIS}
* miliseconds and the event is the same kind of event as the given one,
* merge or delete both of the events if necessary to reduce hassle
* notifications.
*
* Examples:
*
* - If an assignee was changed from A to B, then A to C, the two events
* are merged into the event of which assignee was changed from A to C.
* - If an assignee was changed from A to B, then B to A, the two events
* will be deleted.
*
* Notes: This method originates from
* {@link NotificationEvent#add(NotificationEvent)}
*
* @param event
*/
public static void add(IssueEvent event) {
Date draftDate = DateTime.now().minusMillis(DRAFT_TIME_IN_MILLIS).toDate();
IssueEvent lastEvent = IssueEvent.find.where()
.eq("issue.id", event.issue.id)
.gt("created", draftDate)
.orderBy("id desc").setMaxRows(1).findUnique();
if (lastEvent != null) {
if (lastEvent.eventType == event.eventType &&
StringUtils.equals(event.senderLoginId, lastEvent.senderLoginId)) {
// A -> B, B -> C ==> A -> C
event.oldValue = lastEvent.oldValue;
lastEvent.delete();
// A -> B, B -> A ==> remove all of them
if (StringUtils.equals(event.oldValue, event.newValue)) {
// No need to add this event because the event just cancels the last event
// which has just been deleted.
return;
}
}
}
event.save();
}
/**
* Adds events based on the given {@code notiEvent}, {@code updatedIssue}
* and {@code senderLoginId}.
*
* @param notiEvent
* @param updatedIssue
* @param senderLoginId
* @see {@link #add(IssueEvent)}
*/
public static void addFromNotificationEvent(NotificationEvent notiEvent, Issue updatedIssue,
String senderLoginId) {
IssueEvent event = new IssueEvent();
event.created = notiEvent.created;
event.senderLoginId = senderLoginId;
event.issue = updatedIssue;
event.eventType = notiEvent.eventType;
event.oldValue = notiEvent.oldValue;
event.newValue = notiEvent.newValue;
add(event);
}
@Override
public Date getDate() {
return created;
}
public static Set<Issue> findReferredIssue(String message, Project project) {
Matcher m = Issue.ISSUE_PATTERN.matcher(message);
Set<Issue> referredIssues = new HashSet<>();
while(m.find()) {
String issueText = m.group();
String issueNumber = issueText.substring(1); // removing the leading char #
Issue issue = Issue.findByNumber(project, Long.parseLong(issueNumber));
if(issue != null) {
referredIssues.add(issue);
}
}
return referredIssues;
}
}