blob: 689aa2a1a1d883c16b25af4d4890d80a80708fc4 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// 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 com.google.gerrit.client.change;
import com.google.gerrit.client.changes.CommentApi;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.diff.CommentRange;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.Cookies;
import java.util.ArrayList;
import java.util.Collection;
public class LocalComments {
private final Change.Id changeId;
private final PatchSet.Id psId;
private final StorageBackend storage;
private static class InlineComment {
final PatchSet.Id psId;
final CommentInfo commentInfo;
InlineComment(PatchSet.Id psId, CommentInfo commentInfo) {
this.psId = psId;
this.commentInfo = commentInfo;
}
}
private static class StorageBackend {
private final Storage storageBackend;
StorageBackend() {
storageBackend =
(Storage.isLocalStorageSupported())
? Storage.getLocalStorageIfSupported()
: Storage.getSessionStorageIfSupported();
}
String getItem(String key) {
if (storageBackend == null) {
return Cookies.getCookie(key);
}
return storageBackend.getItem(key);
}
void setItem(String key, String value) {
if (storageBackend == null) {
Cookies.setCookie(key, value);
return;
}
storageBackend.setItem(key, value);
}
void removeItem(String key) {
if (storageBackend == null) {
Cookies.removeCookie(key);
return;
}
storageBackend.removeItem(key);
}
Collection<String> getKeys() {
if (storageBackend == null) {
return Cookies.getCookieNames();
}
ArrayList<String> result = new ArrayList<>(storageBackend.getLength());
for (int i = 0; i < storageBackend.getLength(); i++) {
result.add(storageBackend.key(i));
}
return result;
}
}
public LocalComments(Change.Id changeId) {
this.changeId = changeId;
this.psId = null;
this.storage = new StorageBackend();
}
public LocalComments(PatchSet.Id psId) {
this.changeId = psId.getParentKey();
this.psId = psId;
this.storage = new StorageBackend();
}
public String getReplyComment() {
String comment = storage.getItem(getReplyCommentName());
storage.removeItem(getReplyCommentName());
return comment;
}
public void setReplyComment(String comment) {
storage.setItem(getReplyCommentName(), comment.trim());
}
public boolean hasReplyComment() {
return storage.getKeys().contains(getReplyCommentName());
}
public void removeReplyComment() {
if (hasReplyComment()) {
storage.removeItem(getReplyCommentName());
}
}
private String getReplyCommentName() {
return "savedReplyComment-" + changeId.toString();
}
public static void saveInlineComments() {
final StorageBackend storage = new StorageBackend();
for (final String cookie : storage.getKeys()) {
if (isInlineComment(cookie)) {
InlineComment input = getInlineComment(cookie);
if (input.commentInfo.id() == null) {
CommentApi.createDraft(
input.psId,
input.commentInfo,
new GerritCallback<CommentInfo>() {
@Override
public void onSuccess(CommentInfo result) {
storage.removeItem(cookie);
}
});
} else {
CommentApi.updateDraft(
input.psId,
input.commentInfo.id(),
input.commentInfo,
new GerritCallback<CommentInfo>() {
@Override
public void onSuccess(CommentInfo result) {
storage.removeItem(cookie);
}
@Override
public void onFailure(Throwable caught) {
if (RestApi.isNotFound(caught)) {
// the draft comment, that was supposed to be updated,
// was deleted in the meantime
storage.removeItem(cookie);
} else {
super.onFailure(caught);
}
}
});
}
}
}
}
public void setInlineComment(CommentInfo comment) {
String name = getInlineCommentName(comment);
if (name == null) {
// Failed to get the store key -- so we can't continue.
return;
}
storage.setItem(name, comment.message().trim());
}
public boolean hasInlineComments() {
for (String cookie : storage.getKeys()) {
if (isInlineComment(cookie)) {
return true;
}
}
return false;
}
private static boolean isInlineComment(String key) {
return key.startsWith("patchCommentEdit-")
|| key.startsWith("patchReply-")
|| key.startsWith("patchComment-");
}
private static InlineComment getInlineComment(String key) {
String path;
Side side = Side.PARENT;
int line = 0;
CommentRange range;
StorageBackend storage = new StorageBackend();
String[] elements = key.split("-");
int offset = 1;
if (key.startsWith("patchReply-") || key.startsWith("patchCommentEdit-")) {
offset = 2;
}
Change.Id changeId = new Change.Id(Integer.parseInt(elements[offset + 0]));
PatchSet.Id psId = new PatchSet.Id(changeId, Integer.parseInt(elements[offset + 1]));
path = atob(elements[offset + 2]);
side = (Side.PARENT.toString().equals(elements[offset + 3])) ? Side.PARENT : Side.REVISION;
range = null;
if (elements[offset + 4].startsWith("R")) {
String rangeStart = elements[offset + 4].substring(1);
String rangeEnd = elements[offset + 5];
String[] split = rangeStart.split(",");
int sl = Integer.parseInt(split[0]);
int sc = Integer.parseInt(split[1]);
split = rangeEnd.split(",");
int el = Integer.parseInt(split[0]);
int ec = Integer.parseInt(split[1]);
range = CommentRange.create(sl, sc, el, ec);
line = sl;
} else {
line = Integer.parseInt(elements[offset + 4]);
}
CommentInfo info = CommentInfo.create(path, side, line, range, false);
info.message(storage.getItem(key));
if (key.startsWith("patchReply-")) {
info.inReplyTo(elements[1]);
} else if (key.startsWith("patchCommentEdit-")) {
info.id(elements[1]);
}
InlineComment inlineComment = new InlineComment(psId, info);
return inlineComment;
}
private String getInlineCommentName(CommentInfo comment) {
if (psId == null) {
return null;
}
String result = "patchComment-";
if (comment.id() != null) {
result = "patchCommentEdit-" + comment.id() + "-";
} else if (comment.inReplyTo() != null) {
result = "patchReply-" + comment.inReplyTo() + "-";
}
result +=
changeId + "-" + psId.getId() + "-" + btoa(comment.path()) + "-" + comment.side() + "-";
if (comment.hasRange()) {
result +=
"R"
+ comment.range().startLine()
+ ","
+ comment.range().startCharacter()
+ "-"
+ comment.range().endLine()
+ ","
+ comment.range().endCharacter();
} else {
result += comment.line();
}
return result;
}
private static native String btoa(String a) /*-{ return btoa(a); }-*/;
private static native String atob(String b) /*-{ return atob(b); }-*/;
}