package scrum.server.project;
import ilarkesto.base.Money;
import ilarkesto.base.Str;
import ilarkesto.base.Utl;
import ilarkesto.base.time.Date;
import ilarkesto.persistence.AEntity;
import ilarkesto.persistence.Persist;
import ilarkesto.rss.Rss20Builder;
import ilarkesto.search.Searchable;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import scrum.client.UsersStatusData;
import scrum.server.ScrumConfig;
import scrum.server.admin.ProjectUserConfig;
import scrum.server.admin.ProjectUserConfigDao;
import scrum.server.admin.User;
import scrum.server.calendar.SimpleEvent;
import scrum.server.calendar.SimpleEventDao;
import scrum.server.collaboration.Comment;
import scrum.server.collaboration.CommentDao;
import scrum.server.collaboration.Subject;
import scrum.server.collaboration.SubjectDao;
import scrum.server.collaboration.Wikipage;
import scrum.server.collaboration.WikipageDao;
import scrum.server.estimation.RequirementEstimationVote;
import scrum.server.estimation.RequirementEstimationVoteDao;
import scrum.server.files.File;
import scrum.server.files.FileDao;
import scrum.server.impediments.Impediment;
import scrum.server.impediments.ImpedimentDao;
import scrum.server.issues.Issue;
import scrum.server.issues.IssueDao;
import scrum.server.journal.ProjectEvent;
import scrum.server.journal.ProjectEventDao;
import scrum.server.pr.BlogEntry;
import scrum.server.pr.BlogEntryDao;
import scrum.server.release.Release;
import scrum.server.release.ReleaseDao;
import scrum.server.risks.Risk;
import scrum.server.risks.RiskDao;
import scrum.server.sprint.Sprint;
import scrum.server.sprint.SprintDaySnapshot;
import scrum.server.sprint.SprintDaySnapshotDao;
import scrum.server.sprint.Task;
import scrum.server.sprint.TaskDao;
public class Project extends GProject {
private transient UsersStatusData usersStatus;
private transient Comparator<Requirement> requirementsOrderComparator;
// --- dependencies ---
private static ProjectUserConfigDao projectUserConfigDao;
private static ImpedimentDao impedimentDao;
private static IssueDao issueDao;
private static RequirementDao requirementDao;
private static QualityDao qualityDao;
private static ProjectSprintSnapshotDao projectSprintSnapshotDao;
private static RiskDao riskDao;
private static TaskDao taskDao;
private static WikipageDao wikipageDao;
private static ProjectEventDao projectEventDao;
private static SimpleEventDao simpleEventDao;
private static FileDao fileDao;
private static ScrumConfig config;
private static CommentDao commentDao;
private static ReleaseDao releaseDao;
private static RequirementEstimationVoteDao requirementEstimationVoteDao;
private static SprintDaySnapshotDao sprintDaySnapshotDao;
private static SubjectDao subjectDao;
private static BlogEntryDao blogEntryDao;
public static void setBlogEntryDao(BlogEntryDao blogEntryDao) {
Project.blogEntryDao = blogEntryDao;
}
public static void setSubjectDao(SubjectDao subjectDao) {
Project.subjectDao = subjectDao;
}
public static void setCommentDao(CommentDao commentDao) {
Project.commentDao = commentDao;
}
public static void setSprintDaySnapshotDao(SprintDaySnapshotDao sprintDaySnapshotDao) {
Project.sprintDaySnapshotDao = sprintDaySnapshotDao;
}
public static void setRequirementEstimationVoteDao(RequirementEstimationVoteDao requirementEstimationVoteDao) {
Project.requirementEstimationVoteDao = requirementEstimationVoteDao;
}
public static void setReleaseDao(ReleaseDao releaseDao) {
Project.releaseDao = releaseDao;
}
public static void setConfig(ScrumConfig config) {
Project.config = config;
}
public static void setFileDao(FileDao fileDao) {
Project.fileDao = fileDao;
}
public static void setSimpleEventDao(SimpleEventDao simpleEventDao) {
Project.simpleEventDao = simpleEventDao;
}
public static void setProjectEventDao(ProjectEventDao projectEventDao) {
Project.projectEventDao = projectEventDao;
}
public static void setWikipageDao(WikipageDao wikipageDao) {
Project.wikipageDao = wikipageDao;
}
public static void setProjectUserConfigDao(ProjectUserConfigDao projectUserConfigDao) {
Project.projectUserConfigDao = projectUserConfigDao;
}
public static void setIssueDao(IssueDao issueDao) {
Project.issueDao = issueDao;
}
public static void setTaskDao(TaskDao taskDao) {
Project.taskDao = taskDao;
}
public static void setRiskDao(RiskDao riskDao) {
Project.riskDao = riskDao;
}
public static void setImpedimentDao(ImpedimentDao impedimentDao) {
Project.impedimentDao = impedimentDao;
}
public static void setRequirementDao(RequirementDao storyDao) {
Project.requirementDao = storyDao;
}
public static void setQualityDao(QualityDao qualityDao) {
Project.qualityDao = qualityDao;
}
public static void setProjectSprintSnapshotDao(ProjectSprintSnapshotDao projectSprintSnapshotDao) {
Project.projectSprintSnapshotDao = projectSprintSnapshotDao;
}
// --- ---
public boolean containsParticipantWithVerifiedEmail() {
for (User user : getParticipants()) {
if (user.isEmailVerified()) return true;
}
return false;
}
public void updateRequirementsOrder(List<Requirement> requirements) {
setRequirementsOrderIds(Persist.getIdsAsList(requirements));
}
public synchronized void updateHomepage() {
if (!isHomepageDirSet()) return;
getHomepageUpdater().processAll();
}
public synchronized void updateHomepage(AEntity entity, boolean forceUpdate) {
if (!isHomepageDirSet()) return;
if (!forceUpdate && !isAutoUpdateHomepage()) return;
getHomepageUpdater().processEntityTemplate(entity);
}
public java.io.File getHomepageDirFile() {
if (!isHomepageDirSet()) return null;
return new java.io.File(getHomepageDir());
}
public String getHomepageVelocityDir() {
if (!isHomepageDirSet()) return null;
return getHomepageDir() + "/velocity";
}
public HomepageUpdater getHomepageUpdater() {
return new HomepageUpdater(this);
}
public void scanFiles() {
java.io.File dir = new java.io.File(getFileRepositoryPath());
java.io.File[] files = dir.listFiles();
if (files != null) {
for (java.io.File f : files) {
File file = fileDao.getFilesByName(f.getName(), this);
if (file == null) {
file = fileDao.postFile(f, this);
}
}
}
}
@SuppressWarnings("unchecked")
public ArrayList<AEntity> search(String text) {
String[] keys = Str.tokenize(text, " ");
ArrayList ret = new ArrayList();
ret.addAll(getMatching(getRequirements(), keys));
ret.addAll(getMatching(getQualitys(), keys));
ret.addAll(getMatching(getTasks(), keys));
ret.addAll(getMatching(getWikipages(), keys));
ret.addAll(getMatching(getIssues(), keys));
ret.addAll(getMatching(getImpediments(), keys));
ret.addAll(getMatching(getRisks(), keys));
ret.addAll(getMatching(getFiles(), keys));
ret.addAll(getMatching(getReleases(), keys));
ret.addAll(getMatching(getBlogEntrys(), keys));
return ret;
}
private <T extends Searchable> List<T> getMatching(Collection<T> entities, String[] keys) {
List<T> ret = new ArrayList<T>();
for (T entity : entities) {
if (matchesKeys(entity, keys)) ret.add(entity);
}
return ret;
}
private boolean matchesKeys(Searchable entity, String[] keys) {
for (String key : keys) {
if (!entity.matchesKey(key)) return false;
}
return true;
}
public void writeJournalAsRss(OutputStream out, String encoding, String baseUrl) {
Rss20Builder rss = new Rss20Builder();
rss.setTitle(getLabel() + " Event Journal");
rss.setLanguage("en");
rss.setLink(baseUrl + "#project=" + getId());
for (ProjectEvent event : getLatestProjectEvents()) {
Rss20Builder.Item item = rss.addItem();
item.setTitle(event.getLabel());
item.setDescription(event.getLabel());
String link = baseUrl + "#project=" + getId();
if (event.isSubjectSet()) link += "|entity=" + event.getSubjectId();
item.setLink(link);
item.setGuid(event.getId());
item.setPubDate(event.getDateAndTime());
}
rss.sortItems();
rss.write(out, encoding);
}
public String getFileRepositoryPath() {
return config.getFileRepositoryPath() + "/" + getId();
}
public Set<SimpleEvent> getCalendarEvents() {
return simpleEventDao.getSimpleEventsByProject(this);
}
public List<ProjectEvent> getLatestProjectEvents() {
List<ProjectEvent> events = new LinkedList<ProjectEvent>(getProjectEvents());
int max = 30;
if (events.size() <= max) return events;
Collections.sort(events);
while (events.size() > max) {
events.remove(0);
}
return events;
}
public Set<ProjectEvent> getProjectEvents() {
return projectEventDao.getProjectEventsByProject(this);
}
public UsersStatusData getUsersStatus() {
if (usersStatus == null) usersStatus = new UsersStatusData();
return usersStatus;
}
public Set<ProjectUserConfig> getUserConfigs() {
Set<ProjectUserConfig> configs = new HashSet<ProjectUserConfig>();
for (User user : getParticipants()) {
configs.add(getUserConfig(user));
}
return configs;
}
public ProjectUserConfig getUserConfig(User user) {
return projectUserConfigDao.getProjectUserConfig(this, user);
}
public Set<Wikipage> getWikipages() {
return wikipageDao.getWikipagesByProject(this);
}
public Set<Task> getTasks() {
return taskDao.getTasksByProject(this);
}
public AEntity getEntityByReference(String reference) {
if (reference.length() > 4 && reference.startsWith("[[")) {
String pageName = reference.substring(2, reference.length() - 2);
return getWikipageByName(pageName);
}
int number = Integer.parseInt(reference.substring(scrum.client.project.Requirement.REFERENCE_PREFIX.length()));
if (reference.startsWith(scrum.client.project.Requirement.REFERENCE_PREFIX)) {
return getRequirementByNumber(number);
} else if (reference.startsWith(scrum.client.project.Quality.REFERENCE_PREFIX)) {
return getQualityByNumber(number);
} else if (reference.startsWith(scrum.client.sprint.Task.REFERENCE_PREFIX)) {
return getTaskByNumber(number);
} else if (reference.startsWith(scrum.client.impediments.Impediment.REFERENCE_PREFIX)) {
return getImpedimentByNumber(number);
} else if (reference.startsWith(scrum.client.issues.Issue.REFERENCE_PREFIX)) {
return getIssueByNumber(number);
} else if (reference.startsWith(scrum.client.sprint.Sprint.REFERENCE_PREFIX)) {
return getSprintByNumber(number);
} else if (reference.startsWith(scrum.client.collaboration.Subject.REFERENCE_PREFIX)) {
return getSubjectByNumber(number);
} else if (reference.startsWith(scrum.client.files.File.REFERENCE_PREFIX)) {
return getFileByNumber(number);
} else if (reference.startsWith(scrum.client.calendar.SimpleEvent.REFERENCE_PREFIX)) {
return getSimpleEventByNumber(number);
} else if (reference.startsWith(scrum.client.release.Release.REFERENCE_PREFIX)) {
return getReleaseByNumber(number);
} else if (reference.startsWith(scrum.client.pr.BlogEntry.REFERENCE_PREFIX)) { return getBlogEntryByNumber(number); }
return null;
}
public Requirement getRequirementByNumber(int number) {
return requirementDao.getRequirementByNumber(number, this);
}
public Task getTaskByNumber(int number) {
return taskDao.getTaskByNumber(number, this);
}
public Quality getQualityByNumber(int number) {
return qualityDao.getQualityByNumber(number, this);
}
public Issue getIssueByNumber(int number) {
return issueDao.getIssueByNumber(number, this);
}
public Sprint getSprintByNumber(int number) {
return sprintDao.getSprintByNumber(number, this);
}
public Impediment getImpedimentByNumber(int number) {
return impedimentDao.getImpedimentByNumber(number, this);
}
public Subject getSubjectByNumber(int number) {
return subjectDao.getSubjectsByNumber(number, this);
}
public File getFileByNumber(int number) {
return fileDao.getFileByNumber(number, this);
}
public File getFileByReference(String reference) {
return getFileByNumber(Integer.parseInt(reference.substring(3)));
}
public SimpleEvent getSimpleEventByNumber(int number) {
return simpleEventDao.getSimpleEventByNumber(number, this);
}
public Release getReleaseByNumber(int number) {
return releaseDao.getReleaseByNumber(number, this);
}
public BlogEntry getBlogEntryByNumber(int number) {
return blogEntryDao.getBlogEntryByNumber(number, this);
}
public Wikipage getWikipageByName(String name) {
return wikipageDao.getWikipageByName(name, this);
}
public synchronized int generateTaskNumber() {
int number = getLastTaskNumber() + 1;
setLastTaskNumber(number);
return number;
}
public synchronized int generateEventNumber() {
int number = getLastEventNumber() + 1;
setLastEventNumber(number);
return number;
}
public synchronized int generateFileNumber() {
int number = getLastFileNumber() + 1;
setLastFileNumber(number);
return number;
}
public synchronized int generateRequirementNumber() {
int number = getLastRequirementNumber() + 1;
setLastRequirementNumber(number);
return number;
}
public synchronized int generateImpedimentNumber() {
int number = getLastImpedimentNumber() + 1;
setLastImpedimentNumber(number);
return number;
}
public synchronized int generateSubjectNumber() {
int number = getLastSubjectNumber() + 1;
setLastSubjectNumber(number);
return number;
}
public synchronized int generateRiskNumber() {
int number = getLastRiskNumber() + 1;
setLastRiskNumber(number);
return number;
}
public synchronized int generateIssueNumber() {
int number = getLastIssueNumber() + 1;
setLastIssueNumber(number);
return number;
}
public synchronized int generateSprintNumber() {
int number = getLastSprintNumber() + 1;
setLastSprintNumber(number);
return number;
}
public synchronized int generateReleaseNumber() {
int number = getLastReleaseNumber() + 1;
setLastReleaseNumber(number);
return number;
}
public synchronized int generateQualityNumber() {
int number = getLastQualityNumber() + 1;
setLastQualityNumber(number);
return number;
}
public synchronized int generateBlogEntryNumber() {
int number = getLastBlogEntryNumber() + 1;
setLastBlogEntryNumber(number);
return number;
}
public Release getCurrentRelease() {
return releaseDao.getCurrentRelease(this);
}
public Release getNextRelease() {
return releaseDao.getNextRelease(this);
}
public ProjectSprintSnapshot getCurrentSprintSnapshot() {
ProjectSprintSnapshot snapshot = projectSprintSnapshotDao.getProjectSprintSnapshotBySprint(getCurrentSprint());
if (snapshot == null) snapshot = createSprintSnapshot();
return snapshot;
}
// public int getRemainingWork() {
// int sum = 0;
// for (Requirement requirement : getRequirements()) {
// if (requirement.isClosed()) continue;
// Integer work = requirement.getEstimatedWork();
// if (work != null) sum += work;
// }
// return sum;
// }
//
// public int getBurnedWork() {
// int sum = 0;
// for (Requirement requirement : getRequirements()) {
// if (!requirement.isClosed()) continue;
// Integer work = requirement.getEstimatedWork();
// if (work != null) sum += work;
// }
// return sum;
// }
public List<ProjectSprintSnapshot> getSprintSnapshots() {
return projectSprintSnapshotDao.getProjectSprintSnapshotsByProject(this);
}
public void switchToNextSprint() {
Sprint oldSprint = getCurrentSprint();
oldSprint.close();
oldSprint.setEnd(Date.today());
getCurrentSprintSnapshot().update();
Sprint newSprint = getNextSprint();
if (newSprint == null) newSprint = createNextSprint();
if (!newSprint.isBeginSet() || newSprint.getBegin().isPast()) newSprint.setBegin(Date.today());
if (!newSprint.isEndSet() || newSprint.getEnd().isBeforeOrSame(newSprint.getBegin()))
newSprint.setEnd(newSprint.getBegin().addDays(oldSprint.getLengthInDays()));
setCurrentSprint(newSprint);
createNextSprint();
createSprintSnapshot();
for (Task task : oldSprint.getTasks()) {
if (task.isClosed()) {
taskDao.deleteEntity(task);
}
}
}
private ProjectSprintSnapshot createSprintSnapshot() {
ProjectSprintSnapshot snapshot = projectSprintSnapshotDao.newEntityInstance();
snapshot.setSprint(getCurrentSprint());
snapshot.update();
projectSprintSnapshotDao.saveEntity(snapshot);
return snapshot;
}
public Sprint createNextSprint() {
Sprint sprint = sprintDao.newEntityInstance();
sprint.setProject(this);
sprint.setLabel("Next Sprint");
if (isCurrentSprintSet()) {
sprint.setBegin(getCurrentSprint().getEnd());
Integer length = getCurrentSprint().getLengthInDays();
if (length != null) sprint.setEnd(sprint.getBegin().addDays(length));
}
sprintDao.saveEntity(sprint);
setNextSprint(sprint);
return sprint;
}
public Set<Sprint> getSprints() {
return sprintDao.getSprintsByProject(this);
}
public Set<Impediment> getImpediments() {
return impedimentDao.getImpedimentsByProject(this);
}
public Set<Issue> getIssues() {
return issueDao.getIssuesByProject(this);
}
public Set<Issue> getAcceptedIssues() {
return issueDao.getAcceptedIssues(this);
}
public Set<Issue> getClosedIssues() {
return issueDao.getClosedIssues(this);
}
public Set<Issue> getOpenIssues() {
return issueDao.getOpenIssues(this);
}
public Set<Issue> getPublishedIssues() {
return issueDao.getPublishedIssues(this);
}
public Set<Issue> getBugsInCurrentRelease() {
Release release = getCurrentRelease();
Release nextRelease = getNextRelease();
if (release == null) return getOpenBugs();
Set<Issue> ret = new HashSet<Issue>();
ret.addAll(getOpenBugs());
for (Issue issue : getClosedIssues()) {
if (issue.containsFixRelease(nextRelease) && !issue.containsFixRelease(release)) ret.add(issue);
}
return ret;
}
public Set<Issue> getOpenBugs() {
return issueDao.getOpenBugs(this);
}
public Set<Issue> getOpenIdeas() {
return issueDao.getOpenIdeas(this);
}
public Set<Risk> getRisks() {
return riskDao.getRisksByProject(this);
}
public Set<Requirement> getRequirements() {
return requirementDao.getRequirementsByProject(this);
}
public Set<File> getFiles() {
return fileDao.getFilesByProject(this);
}
public Set<Subject> getSubjects() {
return subjectDao.getSubjectsByProject(this);
}
public Set<Release> getReleases() {
return releaseDao.getReleasesByProject(this);
}
public Set<BlogEntry> getBlogEntrys() {
return blogEntryDao.getBlogEntrysByProject(this);
}
public Set<RequirementEstimationVote> getRequirementEstimationVotes() {
Set<RequirementEstimationVote> ret = new HashSet<RequirementEstimationVote>();
for (Requirement requirement : getRequirements()) {
ret.addAll(requirement.getEstimationVotes());
}
return ret;
}
public Set<SprintDaySnapshot> getSprintDaySnapshots() {
Set<SprintDaySnapshot> ret = new HashSet<SprintDaySnapshot>();
for (Sprint sprint : getSprints()) {
ret.addAll(sprint.getDaySnapshots());
}
return ret;
}
public Set<SprintDaySnapshot> getExistingSprintDaySnapshots() {
Set<SprintDaySnapshot> ret = new HashSet<SprintDaySnapshot>();
for (Sprint sprint : getSprints()) {
ret.addAll(sprint.getExistingDaySnapshots());
}
return ret;
}
public Set<SimpleEvent> getSimpleEvents() {
return simpleEventDao.getSimpleEventsByProject(this);
}
public Set<Comment> getAllComments() {
return getComments(false);
}
public Set<Comment> getLatestComments() {
return getComments(true);
}
private Set<Comment> getComments(boolean latestOnly) {
Set<Comment> ret = new HashSet<Comment>();
ret.addAll(getComments(Arrays.asList(this), latestOnly));
ret.addAll(getComments(getSprints(), latestOnly));
ret.addAll(getComments(getParticipants(), latestOnly));
ret.addAll(getComments(getRequirements(), latestOnly));
ret.addAll(getComments(getQualitys(), latestOnly));
ret.addAll(getComments(getTasks(), latestOnly));
ret.addAll(getComments(getImpediments(), latestOnly));
ret.addAll(getComments(getIssues(), latestOnly));
ret.addAll(getComments(getRisks(), latestOnly));
ret.addAll(getComments(getWikipages(), latestOnly));
ret.addAll(getComments(getSimpleEvents(), latestOnly));
ret.addAll(getComments(getFiles(), latestOnly));
ret.addAll(getComments(getReleases(), latestOnly));
ret.addAll(getComments(getSprintSnapshots(), latestOnly));
ret.addAll(getComments(getRequirementEstimationVotes(), latestOnly));
ret.addAll(getComments(getUserConfigs(), latestOnly));
ret.addAll(getComments(getProjectEvents(), latestOnly));
ret.addAll(getComments(getSubjects(), latestOnly));
ret.addAll(getComments(getReleases(), latestOnly));
ret.addAll(getComments(getBlogEntrys(), latestOnly));
return ret;
}
private Set<Comment> getComments(Collection<? extends AEntity> entities, boolean latestOnly) {
Set<Comment> ret = new HashSet<Comment>();
for (AEntity entity : entities) {
Set<Comment> comments = commentDao.getCommentsByParent(entity);
ret.addAll(latestOnly ? getLatest(comments) : comments);
}
return ret;
}
private Set<Comment> getLatest(Set<Comment> comments) {
if (comments.size() < 2) return comments;
Comment latest = null;
for (Comment comment : comments) {
if (latest == null || comment.getDateAndTime().isAfter(latest.getDateAndTime())) latest = comment;
}
assert latest != null;
return Utl.toSet(latest);
}
public Set<Quality> getQualitys() {
return qualityDao.getQualitysByProject(this);
}
@Override
public String toString() {
return getLabel();
}
@Override
public void ensureIntegrity() {
super.ensureIntegrity();
addParticipants(getAdmins());
addParticipants(getProductOwners());
addParticipants(getScrumMasters());
addParticipants(getTeamMembers());
if (!isCurrentSprintSet()) {
Sprint sprint = sprintDao.newEntityInstance();
sprint.setProject(this);
sprintDao.saveEntity(sprint);
setCurrentSprint(sprint);
}
if (!isNextSprintSet()) {
createNextSprint();
}
if (!isPunishmentUnitSet()) {
setPunishmentUnit(Money.EUR);
}
if (getPunishmentFactor() == 0) {
setPunishmentFactor(1);
}
if (!isHomepageDirSet()) setAutoUpdateHomepage(false);
}
@Override
public boolean isVisibleFor(User user) {
return (user != null && user.isAdmin()) || containsParticipant(user) || containsAdmin(user);
}
public boolean isEditableBy(User user) {
return isVisibleFor(user);
}
@Override
public boolean isDeletableBy(User user) {
if (user != null && user.isAdmin()) return true;
return containsAdmin(user);
}
// --- test data ---
public void addTestImpediments() {
Impediment imp = null;
// no documentation
imp = impedimentDao.postImpediment(this, Date.randomPast(5), "There is no documentation. Seriously.", false);
imp.setDescription("Someone promised that, I remember. Where is it?");
// no daily scrums
imp = impedimentDao.postImpediment(this, Date.randomPast(5), "Daily Scrums are not daily", true);
imp.setDescription("\"Daily Scrums\" are supposed to be daily. That's why they are called DAILY Scrums.");
imp.setSolution("Fixed time and place to 09.00 p. m. at Starbucks every morning (except weekdays, weekends and holydays).");
// no coffee
imp = impedimentDao.postImpediment(this, Date.randomPast(5), "There is no coffee machine", false);
}
public void addTestRisks() {
Risk rsk = null;
// god
rsk = riskDao.postRisk(this, "God comes to judge the living and the dead", 0, 100);
rsk.setImpactMitigation("Nothing we can do here.");
// duke
rsk = riskDao.postRisk(this, "Duke Nukem Forever is released", 20, 100);
rsk.setProbabilityMitigation("Nothing to mitigate here. The probability is close to nothing.");
rsk.setImpactMitigation("Nothing to mitigate here. Everyone will be playing. Everything will be lost.");
// sudden death
rsk = riskDao.postRisk(this, "Sudden Death", 50, 40);
rsk.setImpactMitigation("Go to the roof if it's by rising sea level.");
}
public void addTestSimpleEvents() {
// let people generate their own events
}
public void addTestEvents() {
// no test events
}
public void addTestIssues() {
Issue iss = null;
// noobs
iss = issueDao.postIssue(this, "thiz cr4p don't work, n00bz!!1");
iss.setDescription("go home, u noobz ..#");
// eclipse integration
iss = issueDao.postIssue(this, "I want eclipse integration");
iss.setDescription("I would be really nice if eclipse commits would be represented in Kunagi! Thank you!");
// link bug
iss = issueDao.postIssue(this, "Bug: Links don't work");
iss.setDescription("When I try to post links to other pages, I get links to the Wiki. WTF?");
// date crash
iss = issueDao.postIssue(this, "Crash when using Dates after 2012");
iss.setDescription("The program crashes whenever I enter dates after 2012. Can't figure out what the problem is though.");
iss.setAcceptDate(Date.beforeDays(2));
iss.setUrgent(true);
iss.setSeverity(scrum.client.issues.Issue.SEVERE);
// gui bug
iss = issueDao.postIssue(this, "GUI inconsistency between PB and SB");
iss.setDescription("The order of Qualities and Tests is different between widgets in the PB and SB. It should be the same.");
iss.setAcceptDate(Date.beforeDays(35));
iss.setUrgent(true);
iss.setSeverity(scrum.client.issues.Issue.MINOR);
// navi display bug
iss = issueDao.postIssue(this, "navigation displays wrong current view");
iss.setDescription("When I open the Whiteboard, \"Sprint Backlog\" is selected in the navigation. Same for other jumps.");
iss.setAcceptDate(Date.today());
iss.setUrgent(true);
iss.setSeverity(scrum.client.issues.Issue.MINOR);
iss.setIssuerName("Witek");
iss.setIssuerEmail("wi@koczewski.de");
// terrific pb suggestion
iss = issueDao.postIssue(this, "Product Backlog should be terrific, not amazing");
iss.setDescription("56% of users want a terrific PB, not an amazing one. We should change that in one of the upcoming releases.");
iss.setAcceptDate(Date.today());
// flattr
iss = issueDao.postIssue(this, "Add a flattr-button");
iss.setDescription("See [http://flattr.com].");
iss.setCloseDate(Date.beforeDays(1));
// thank you
iss = issueDao.postIssue(this, "I like this software, thank you!");
iss.setDescription("I'm using Kunagi for my own project now. Thanks for the great work.");
iss.setCloseDate(Date.today());
}
public void addTestRequirements() {
Requirement req = null;
List<Requirement> reqOrder = new LinkedList<Requirement>();
// Unsurpassed Concept
req = requirementDao.postRequirement(this, "Unsurpassed Concept", 3f);
req.setDescription("As a Product Owner I want the concept to be unsurpassable so I don't have to worry about ROI anymore.");
reqOrder.add(req);
req.setSprint(getCurrentSprint());
taskDao.postTask(req, "Create Concept", 20);
taskDao.postTask(req, "Make Sure All Others Are Inferior", 50);
// Amazing Product Backlog
req = requirementDao.postRequirement(this, "Amazing Product Backlog", 2f);
req.setDescription("As a Product Owner I want my Backlog to be amazing so that people stand in awe.");
reqOrder.add(req);
req.setSprint(getCurrentSprint());
taskDao.postTask(req, "Creation of Storys", 10);
taskDao.postTask(req, "Intelligent Design of Storys", 10);
taskDao.postTask(req, "Deletion of Storys", 10);
// Functional Quality Backlog
req = requirementDao.postRequirement(this, "Functional Quality Backlog", 1f);
req.setDescription("As a Product Owner I want my non-functional Requirements to be functional, so I can use them.");
reqOrder.add(req);
req.setSprint(getCurrentSprint());
taskDao.postTask(req, "Copy And Paste Product Backlog", 10);
taskDao.postTask(req, "Marry Storys and Qualitys", 10);
// Groundbraking Scrum Backlog
req = requirementDao.postRequirement(this, "Groundbraking Scrum Backlog", 1f);
req.setDescription("As a Team member I want the Scrum Backlog to be groundbreaking, so that everybody can see that I am the most important here.");
reqOrder.add(req);
req.setSprint(getCurrentSprint());
taskDao.postTask(req, "Create Tasks", 10);
taskDao.postTask(req, "Create More Tasks", 10);
// Breathtaking Whiteboard
req = requirementDao.postRequirement(this, "Breathtaking Whiteboard", 8f);
req.setDescription("As a Team member I want the current state of things to be displayed on a Whiteboard, so I can play around when I am bored.");
reqOrder.add(req);
// Empowering Impediment List
req = requirementDao.postRequirement(this, "Empowering Impediment List", 2f);
req.setDescription("As a Scrum Master I want the Impedimen List to be empowering. Best thing would be self-resolving Impediments.");
reqOrder.add(req);
// Divine Risk Management
req = requirementDao.postRequirement(this, "Divine Risk Management", 5f);
req.setDescription("As a Team member, I want Risk Management to be devine. Wait, that makes Risk Management superfluous, I guess.");
reqOrder.add(req);
// Miraculous Issue Management
req = requirementDao.postRequirement(this, "Miraculous Issue Management", 3f);
req.setDescription("As a Product Owner I want my Issue Management to be miraculous, so that Issues close themselves AND sometimes even each other.");
reqOrder.add(req);
// Immaculate Bug Tracking
req = requirementDao.postRequirement(this, "Immaculate Bug Tracking", 2f);
req.setDescription("As a Team member I want immaculate Bug Tracking. A Bug Tracking containing no bugs would be suitable.");
reqOrder.add(req);
// Unbeatable Planning Poker
req = requirementDao.postRequirement(this, "Unbeatable Planning Poker", null);
req.setDescription("As I User I want Planning Poker to be so good that nobody can beat it.");
reqOrder.add(req);
// Enlightening Wiki
req = requirementDao.postRequirement(this, "Enlightening Wiki", 5f);
req.setDescription("As a User I want the Wiki to enlighten me so that I am enlightened after reading (makes sense, doesn't it?).");
reqOrder.add(req);
// Absorbing Discussion Board
req = requirementDao.postRequirement(this, "Absorbing Discussion Board", 5f);
req.setDescription("As a User I want the Discussion Board to be absorbing, so that I never have time to do my work.");
reqOrder.add(req);
// Irresistable User Interface
req = requirementDao.postRequirement(this, "Irresistable User Interface", 20f);
req.setDescription("As a User I want the User Interface to be irresistable so that I can experience Orgasmic Joy-of-Use.");
reqOrder.add(req);
// Succulent Documentation
req = requirementDao.postRequirement(this, "Succulent Documentation", null);
req.setDescription("As a Noob I want Succulent Documentation. Yammy!");
reqOrder.add(req);
// Outlasting Collaboration
req = requirementDao.postRequirement(this, "Outlasting Collaboration", null);
req.setDescription("This is still an epic. Nothing to see, really.");
reqOrder.add(req);
updateRequirementsOrder(reqOrder);
}
public void addTestQualitys() {
Quality qly = null;
qly = qualityDao.postQuality(this, "Undeniable Success");
qly = qualityDao.postQuality(this, "Orgasmic Joy-of-Use");
qly = qualityDao.postQuality(this, "Effervescent Happiness");
qly = qualityDao.postQuality(this, "Supersonic Communication");
qly = qualityDao.postQuality(this, "Endless Freedom");
qly = qualityDao.postQuality(this, "Flawless Integration");
}
public void addTestSprints() {
sprintDao.createTestSprint(this);
}
public Comparator<Requirement> getRequirementsOrderComparator() {
if (requirementsOrderComparator == null) requirementsOrderComparator = new Comparator<Requirement>() {
@Override
public int compare(Requirement a, Requirement b) {
if (a.isInCurrentSprint() && !b.isInCurrentSprint()) return -1;
if (b.isInCurrentSprint() && !a.isInCurrentSprint()) return 1;
List<String> order = getRequirementsOrderIds();
int additional = order.size();
int ia = order.indexOf(a.getId());
if (ia < 0) {
ia = additional;
additional++;
}
int ib = order.indexOf(b.getId());
if (ib < 0) {
ib = additional;
additional++;
}
return ia - ib;
}
};
return requirementsOrderComparator;
}
}