1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.atlassian.theplugin.idea.ui.tree.file;
18
19 import com.atlassian.theplugin.commons.BambooFileInfo;
20 import com.atlassian.theplugin.commons.VersionedFileInfo;
21 import com.atlassian.theplugin.commons.bamboo.BambooChangeSet;
22 import com.atlassian.theplugin.commons.crucible.api.model.CrucibleFileInfo;
23 import com.atlassian.theplugin.idea.IdeaHelper;
24 import com.atlassian.theplugin.idea.crucible.ReviewData;
25 import com.atlassian.theplugin.idea.crucible.comments.CrucibleReviewActionListener;
26 import com.atlassian.theplugin.idea.crucible.comments.ReviewActionEventBroker;
27 import com.atlassian.theplugin.idea.crucible.events.FocusOnFileComments;
28 import com.atlassian.theplugin.idea.crucible.events.FocusOnGeneralComments;
29 import com.atlassian.theplugin.idea.crucible.events.ShowFileEvent;
30 import com.atlassian.theplugin.idea.ui.tree.AtlassianClickAction;
31 import com.atlassian.theplugin.idea.ui.tree.AtlassianTreeModel;
32 import com.atlassian.theplugin.idea.ui.tree.AtlassianTreeNode;
33 import com.atlassian.theplugin.util.CodeNavigationUtil;
34 import com.intellij.openapi.project.Project;
35 import com.intellij.psi.PsiFile;
36 import com.intellij.psi.PsiManager;
37 import org.jetbrains.annotations.Nullable;
38
39 import java.util.ArrayList;
40 import java.util.List;
41
42 public final class FileTreeModelBuilder {
43
44 private FileTreeModelBuilder() {
45
46 }
47
48 public static AtlassianTreeModel buildTreeModelFromBambooChangeSet(Project project, BambooChangeSet changeSet) {
49 FileNode root = new FolderNode("/");
50 FileTreeModel model = new FileTreeModel(root);
51 for (BambooFileInfo f : changeSet.getFiles()) {
52 model.addFile(project, root, f);
53 }
54 model.compactModel(model.getRoot());
55 return model;
56 }
57
58 @Nullable
59 private static PsiFile guessCorrespondingPsiFile(final Project project, BambooFileInfo file) {
60 final PsiFile[] psifiles = PsiManager.getInstance(project).getShortNamesCache().getFilesByName(
61 file.getFileDescriptor().getName());
62 return CodeNavigationUtil.guessMatchingFile(file.getFileDescriptor().getUrl(), psifiles, project.getBaseDir());
63 }
64
65 public static AtlassianTreeModel buildFlatTreeModelFromBambooChangeSet(final Project project, BambooChangeSet changeSet) {
66 FileTreeModel model = new FileTreeModel(new FolderNode("/"));
67 for (BambooFileInfo f : changeSet.getFiles()) {
68 PsiFile psiFile = guessCorrespondingPsiFile(project, f);
69 model.getRoot().addChild(new BambooFileNode(f, psiFile));
70 }
71 return model;
72 }
73
74
75 public static AtlassianTreeModel buildFlatModelFromCrucibleChangeSet(final Project project, final ReviewData review,
76 List<CrucibleFileInfo> files) {
77 AtlassianTreeModel model = new FileTreeModel(new CrucibleChangeSetTitleNode(review, new AtlassianClickAction() {
78 public void execute(AtlassianTreeNode node, int noOfClicks) {
79 switch (noOfClicks) {
80 case 1:
81 case 2:
82 ReviewActionEventBroker broker = IdeaHelper.getReviewActionEventBroker(project);
83 broker.trigger(new FocusOnGeneralComments(CrucibleReviewActionListener.ANONYMOUS, review));
84 break;
85 default:
86 }
87 }
88 }));
89 for (final CrucibleFileInfo file : files) {
90
91 CrucibleFileNode childNode = new CrucibleFileNode(review, file, new AtlassianClickAction() {
92 public void execute(AtlassianTreeNode node, int noOfClicks) {
93 ReviewActionEventBroker broker = IdeaHelper.getReviewActionEventBroker(project);
94 switch (noOfClicks) {
95 case 1:
96 broker.trigger(
97 new FocusOnFileComments(CrucibleReviewActionListener.ANONYMOUS, review, file));
98 break;
99 case 2:
100 broker.trigger(new ShowFileEvent(CrucibleReviewActionListener.ANONYMOUS, review, file));
101 break;
102 default:
103 break;
104 }
105 }
106 });
107
108 model.getRoot().addNode(childNode);
109
110 }
111 return model;
112 }
113
114 public static AtlassianTreeModel buildTreeModelFromCrucibleChangeSet(final Project project, final ReviewData review,
115 final List<CrucibleFileInfo> files) {
116 FileNode root = new CrucibleChangeSetTitleNode(review, new AtlassianClickAction() {
117 public void execute(AtlassianTreeNode node, int noOfClicks) {
118 switch (noOfClicks) {
119 case 1:
120 case 2:
121 ReviewActionEventBroker broker = IdeaHelper.getReviewActionEventBroker(project);
122 broker.trigger(new FocusOnGeneralComments(CrucibleReviewActionListener.ANONYMOUS, review));
123 break;
124 default:
125 }
126 }
127 });
128 FileTreeModel model = new FileTreeModel(root);
129 for (final CrucibleFileInfo f : files) {
130
131 CrucibleFileNode childNode = new CrucibleFileNode(review, f, new AtlassianClickAction() {
132 public void execute(AtlassianTreeNode node, int noOfClicks) {
133 ReviewActionEventBroker broker = IdeaHelper.getReviewActionEventBroker(project);
134 switch (noOfClicks) {
135 case 1:
136 broker.trigger(new FocusOnFileComments(CrucibleReviewActionListener.ANONYMOUS, review, f));
137 break;
138 case 2:
139 broker.trigger(new ShowFileEvent(CrucibleReviewActionListener.ANONYMOUS, review, f));
140 break;
141 default:
142 break;
143 }
144 }
145 });
146
147 FileNode node = model.createPlace(root, f);
148
149 node.addChild(childNode);
150
151 }
152 model.compactModel(model.getRoot());
153 return model;
154
155
156 }
157
158 private static class FileTreeModel extends AtlassianTreeModel {
159 public FileTreeModel(FileNode root) {
160 super(root);
161 }
162
163 @Override
164 public FileNode getRoot() {
165 return (FileNode) super.getRoot();
166 }
167
168 public void addFile(Project project, FileNode root, BambooFileInfo file) {
169 PsiFile psiFile = guessCorrespondingPsiFile(project, file);
170 FileNode node = createPlace(root, file);
171 node.addChild(new BambooFileNode(file, AtlassianClickAction.EMPTY_ACTION, psiFile));
172 }
173
174 private FileNode createPlace(FileNode root, VersionedFileInfo file) {
175 int idx = 0;
176 String fileName = file.getFileDescriptor().getUrl();
177 FileNode node = root;
178 do {
179 int newIdx = fileName.indexOf('/', idx);
180 if (newIdx != -1) {
181 String newNodeName = fileName.substring(idx, newIdx);
182 if (newNodeName.length() > 0) {
183 if (!node.hasNode(newNodeName)) {
184 FileNode newNode = new FolderNode(newNodeName);
185 node.addChild(newNode);
186 node = newNode;
187 } else {
188 node = node.getNode(newNodeName);
189 }
190 }
191 }
192 idx = newIdx + 1;
193 } while (idx > 0);
194 return node;
195 }
196
197 private void compactModel(FileNode node) {
198 if (node.isLeaf()) {
199 return;
200 }
201
202 java.util.List<FileNode> ch = new ArrayList<FileNode>();
203
204 for (FileNode n : node.getChildren().values()) {
205 ch.add(n);
206 }
207
208 node.removeChildren();
209
210 for (FileNode n : ch) {
211 compactModel(n);
212 if (n.getChildCount() == 1) {
213 FileNode cn = (FileNode) n.getFirstChild();
214 if (!cn.isLeaf()) {
215 String newName = n.getName() + "/" + cn.getName();
216 cn.setName(newName);
217 node.addChild(cn);
218 } else {
219 node.addChild(n);
220 }
221 } else {
222 node.addChild(n);
223 }
224 }
225 }
226
227 }
228 }