/** * Copyright (c) 2011-2012, Thilo Planz. All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package v7cr; import static org.tmatesoft.svn.core.SVNRevisionProperty.AUTHOR; import static org.tmatesoft.svn.core.SVNRevisionProperty.DATE; import static org.tmatesoft.svn.core.SVNRevisionProperty.LOG; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ArrayUtils; import org.bson.BSONObject; import org.bson.BasicBSONObject; import org.bson.types.ObjectId; import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNLogEntryPath; import org.tmatesoft.svn.core.SVNProperties; import org.tmatesoft.svn.core.internal.util.SVNDate; import v7cr.v7db.AccountInfo; import v7cr.v7db.BSONBackedObject; import v7cr.v7db.BSONBackedObjectLoader; import v7cr.v7db.SchemaDefinition; import com.vaadin.ui.Component; import com.vaadin.ui.ComponentContainer; public class Review extends BSONBackedObject { private static final SchemaDefinition schema; static { try { schema = new SchemaDefinition(BSONBackedObjectLoader.parse(IOUtils .toString(Review.class.getResourceAsStream("review.json"), "UTF-8"), null)); } catch (Exception e) { throw new RuntimeException(e); } } public Review(BSONBackedObject bson) { super(bson, schema); } public Review(String project, String title) { this(new BSONBackedObject().append("p", project).append("t", title) .append("s", "new")); } public String getProjectName() { return getStringField("p"); } public String getStatus() { return getStringField("s"); } public String getTitle() { return getStringField("t"); } public AccountInfo getReviewee() { BSONBackedObject b = getObjectField("reviewee"); return b == null ? null : new AccountInfo(b); } public SVNLogEntry getSVNLogEntry() { BSONBackedObject b = getObjectField("svn"); if (b == null) return null; SVNProperties props = new SVNProperties(); props.put(AUTHOR, b.getStringField(AUTHOR)); props.put(DATE, SVNDate.formatDate(b.getDateField(DATE))); props.put(LOG, b.getStringField(LOG)); Map<String, SVNLogEntryPath> changedPaths = null; BSONBackedObject[] changed = b.getObjectFieldAsArray("changed"); if (changed != null) { changedPaths = new TreeMap<String, SVNLogEntryPath>(); for (BSONBackedObject c : changed) { String p = c.getStringField("p"); String t = c.getStringField("t"); changedPaths.put(p, new SVNLogEntryPath(p, t.charAt(0), null, -1)); } } SVNLogEntry svn = new SVNLogEntry(changedPaths, b.getLongField("rev"), props, false); return svn; } public static BSONObject toBSON(SVNLogEntry logEntry) { BSONObject svn = new BasicBSONObject(); svn.put("rev", logEntry.getRevision()); svn.put(AUTHOR, logEntry.getAuthor()); svn.put(DATE, logEntry.getDate()); svn.put(LOG, logEntry.getMessage()); Map<String, SVNLogEntryPath> changedPaths = logEntry.getChangedPaths(); if (changedPaths != null && !changedPaths.isEmpty()) { List<BSONObject> c = new ArrayList<BSONObject>(changedPaths.size()); for (SVNLogEntryPath p : changedPaths.values()) { BSONObject cp = new BasicBSONObject(); cp.put("p", p.getPath()); cp.put("t", String.valueOf(p.getType())); if (p.getCopyPath() != null) { cp.put("cp", p.getCopyPath()); cp.put("crev", p.getCopyRevision()); } c.add(cp); } svn.put("changed", c); } return svn; } public ObjectId getId() { return getObjectIdField("_id"); } public Date getRegistrationDate() { return getDateField("c"); } public Review addVote(AccountInfo user, Date date, String comment, String vote, ComponentContainer files) { BSONObject v = new BasicBSONObject("c", comment).append("d", date) .append("v", vote).append("by", user.getBSONObject()); if (files != null) { Iterator<Component> fi = files.getComponentIterator(); List<BSONObject> fileData = new ArrayList<BSONObject>(); while (fi.hasNext()) { TemporaryFile f = (TemporaryFile) fi.next(); fileData.add(f.file.getBSONObject()); } if (!fileData.isEmpty()) { v.put("files", fileData); } } Review r = new Review(push("v", BSONBackedObjectLoader.wrap(v, null))) .updateStatus(); return r; } public Review deleteVote(BSONBackedObject vote) { BSONBackedObject[] votes = getObjectFieldAsArray("v"); votes = (BSONBackedObject[]) ArrayUtils.removeElement(votes, vote); return new Review(unset("v").pushAll("v", votes)).updateStatus(); } public Review updateVote(BSONBackedObject vote, String newMessage, String rating) { BSONBackedObject[] votes = getObjectFieldAsArray("v"); int idx = ArrayUtils.indexOf(votes, vote); if (idx == -1) return this; votes[idx] = votes[idx].append("c", newMessage).append("v", rating); return new Review(unset("v").pushAll("v", votes)).updateStatus(); } private String calculateStatus() { String status = "new"; BSONBackedObject[] votes = getObjectFieldAsArray("v"); if (votes == null || votes.length == 0) return status; status = "review"; int good = 0; // TODO: very user gets to vote just once for (BSONBackedObject v : votes) { String vv = v.getStringField("v"); if ("-".equals(vv)) return "not good"; if ("+".equals(vv)) good++; } if (good >= 2) return "okay"; return status; } Review updateStatus() { String s = calculateStatus(); if (s.equals(getStatus())) return this; return new Review(append("s", s)); } public static SchemaDefinition getReviewSchemaDefinition() { return schema; } }