// Copyright (C) 2009 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.common.data; import com.google.gerrit.reviewdb.client.PatchLineComment; import com.google.gerrit.reviewdb.client.PatchSet; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class CommentDetail { protected List<PatchLineComment> a; protected List<PatchLineComment> b; protected AccountInfoCache accounts; private transient PatchSet.Id idA; private transient PatchSet.Id idB; private transient Map<Integer, List<PatchLineComment>> forA; private transient Map<Integer, List<PatchLineComment>> forB; public CommentDetail(PatchSet.Id idA, PatchSet.Id idB) { this.a = new ArrayList<>(); this.b = new ArrayList<>(); this.idA = idA; this.idB = idB; } protected CommentDetail() { } public boolean include(final PatchLineComment p) { final PatchSet.Id psId = p.getKey().getParentKey().getParentKey(); switch (p.getSide()) { case 0: if (idA == null && idB.equals(psId)) { a.add(p); return true; } break; case 1: if (idA != null && idA.equals(psId)) { a.add(p); return true; } if (idB.equals(psId)) { b.add(p); return true; } break; } return false; } public void setAccountInfoCache(final AccountInfoCache a) { accounts = a; } public AccountInfoCache getAccounts() { return accounts; } public List<PatchLineComment> getCommentsA() { return a; } public List<PatchLineComment> getCommentsB() { return b; } public boolean isEmpty() { return a.isEmpty() && b.isEmpty(); } public List<PatchLineComment> getForA(final int lineNbr) { if (forA == null) { forA = index(a); } return get(forA, lineNbr); } public List<PatchLineComment> getForB(final int lineNbr) { if (forB == null) { forB = index(b); } return get(forB, lineNbr); } private static List<PatchLineComment> get( final Map<Integer, List<PatchLineComment>> m, final int i) { final List<PatchLineComment> r = m.get(i); return r != null ? orderComments(r) : Collections.<PatchLineComment> emptyList(); } /** * Order the comments based on their parent_uuid parent. It is possible to do this by * iterating over the list only once but it's probably overkill since the number of comments * on a given line will be small most of the time. * * @param comments The list of comments for a given line. * @return The comments sorted as they should appear in the UI */ private static List<PatchLineComment> orderComments(List<PatchLineComment> comments) { // Map of comments keyed by their parent. The values are lists of comments since it is // possible for several comments to have the same parent (this can happen if two reviewers // click Reply on the same comment at the same time). Such comments will be displayed under // their correct parent in chronological order. Map<String, List<PatchLineComment>> parentMap = new HashMap<>(); // It's possible to have more than one root comment if two reviewers create a comment on the // same line at the same time List<PatchLineComment> rootComments = new ArrayList<>(); // Store all the comments in parentMap, keyed by their parent for (PatchLineComment c : comments) { String parentUuid = c.getParentUuid(); List<PatchLineComment> l = parentMap.get(parentUuid); if (l == null) { l = new ArrayList<>(); parentMap.put(parentUuid, l); } l.add(c); if (parentUuid == null) rootComments.add(c); } // Add the comments in the list, starting with the head and then going through all the // comments that have it as a parent, and so on List<PatchLineComment> result = new ArrayList<>(); addChildren(parentMap, rootComments, result); return result; } /** * Add the comments to {@code outResult}, depth first */ private static void addChildren(Map<String, List<PatchLineComment>> parentMap, List<PatchLineComment> children, List<PatchLineComment> outResult) { if (children != null) { for (PatchLineComment c : children) { outResult.add(c); addChildren(parentMap, parentMap.get(c.getKey().get()), outResult); } } } private Map<Integer, List<PatchLineComment>> index( List<PatchLineComment> in) { HashMap<Integer, List<PatchLineComment>> r = new HashMap<>(); for (final PatchLineComment p : in) { List<PatchLineComment> l = r.get(p.getLine()); if (l == null) { l = new ArrayList<>(); r.put(p.getLine(), l); } l.add(p); } return r; } }