View Javadoc

1   /**
2    * Copyright (C) 2008 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.atlassian.theplugin.idea.bamboo;
17  
18  import com.atlassian.theplugin.commons.bamboo.AdjustedBuildStatus;
19  import com.atlassian.theplugin.commons.cfg.BambooServerCfg;
20  import com.atlassian.theplugin.commons.cfg.ProjectId;
21  import com.atlassian.theplugin.commons.remoteapi.ServerData;
22  import com.atlassian.theplugin.commons.util.MiscUtil;
23  import com.atlassian.theplugin.idea.config.GenericComboBoxItemWrapper;
24  import com.atlassian.theplugin.idea.config.ProjectCfgManagerImpl;
25  import com.intellij.ui.ListSpeedSearch;
26  import org.jetbrains.annotations.NotNull;
27  import org.jetbrains.annotations.Nullable;
28  
29  import javax.swing.*;
30  import java.util.Collection;
31  import java.util.LinkedHashSet;
32  import java.util.Set;
33  
34  public class BambooFilterList extends JList {
35  	private final ProjectCfgManagerImpl projectCfgManager;
36  	private final ProjectId projectId;
37  	private final BuildListModelImpl bambooModel;
38  	private BambooFilterType bambooFilterType; // = BambooFilterType.NONE;
39  	private final BamboAllFilterWrapper allFilterWrapper;
40  
41  
42  	public BambooFilterList(final ProjectCfgManagerImpl projectCfgManager,
43  			final ProjectId projectId, final BuildListModelImpl model) {
44  		super(new DefaultListModel());
45  		this.projectCfgManager = projectCfgManager;
46  		this.projectId = projectId;
47  		bambooModel = model;
48  		allFilterWrapper = new BamboAllFilterWrapper(model);
49  		new ListSpeedSearch(this);
50  		updateModel(model.getAllBuilds());
51  	}
52  
53  //	void setSelection(BambooBuildFilter filter) {
54  //
55  //	}
56  
57  	public BambooBuildFilter getSelection() {
58  		return getBuildFilter(getSelectedValues());
59  	}
60  
61  
62  	public void setBambooFilterType(final BambooFilterType bambooFilterType) {
63  		this.bambooFilterType = bambooFilterType;
64  		final DefaultListModel listModel = (DefaultListModel) getModel();
65  		listModel.clear();
66  		updateModel(bambooModel.getAllBuilds());
67  	}
68  
69  	public BambooFilterType getBambooFilterType() {
70  		return bambooFilterType;
71  	}
72  
73  	public void update() {
74  		updateModel(bambooModel.getAllBuilds());
75  		repaint();
76  	}
77  
78  	private void updateModel(@NotNull final Collection<BambooBuildAdapterIdea> buildStatuses) {
79  
80  		final DefaultListModel listModel = (DefaultListModel) getModel();
81  		if (!listModel.contains(allFilterWrapper)) {
82  			listModel.addElement(allFilterWrapper);
83  		}
84  		if (bambooFilterType == null) {
85  			return;
86  		}
87  		switch (bambooFilterType) {
88  			case PROJECT:
89  				Set<String> uniqueBambooProjects = new LinkedHashSet<String>();
90  				for (BambooBuildAdapterIdea buildStatuse : buildStatuses) {
91  					uniqueBambooProjects.add(buildStatuse.getProjectName());
92  				}
93  				for (String bambooProject : uniqueBambooProjects) {
94  					final BamboProjectFilterWrapper obj = new BamboProjectFilterWrapper(new BambooProjectFilter(bambooProject),
95  							bambooModel);
96  					// add those projects which don't exist yet
97  					if (!listModel.contains(obj)) {
98  						listModel.addElement(obj);
99  					}
100 				}
101 				break;
102 			case SERVER:
103 				final Collection<BambooServerCfg> bambooServers = projectCfgManager.getCfgManager()
104 						.getAllEnabledBambooServers(projectId);
105 
106 				for (BambooServerCfg bambooServer : bambooServers) {
107 					final BambooServerFilter serverFilter = new BambooServerFilter(
108 							projectCfgManager.getServerData(bambooServer));
109 					final BamboServerFilterWrapper obj = new BamboServerFilterWrapper(serverFilter,
110 							bambooModel);
111 					if (!listModel.contains(obj)) {
112 						listModel.addElement(obj);
113 					} else {
114 						// as BambooServerCfg objects are mutable and could be just changed in user settings, we need to up
115 						// update them basing on ServerId - the only immutable link.
116 						// I don't like this code, but I have no time now to fight with restoration of user selection
117 						// if I was to reset totally the model of this list
118 						final int i = listModel.indexOf(obj);
119 						if (i != -1) {
120 							final Object o = listModel.get(i);
121 							if (o instanceof BamboServerFilterWrapper) {
122 								BamboServerFilterWrapper wrapper = (BamboServerFilterWrapper) o;
123 								wrapper.updateWrapped(serverFilter);
124 							}
125 						}
126 					}
127 				}
128 
129 				break;
130 			case STATE:
131 				for (AdjustedBuildStatus buildStatus : AdjustedBuildStatus.values()) {
132 					final BuildStatusFilterWrapper obj = new BuildStatusFilterWrapper(new BuildStatusFilter(buildStatus),
133 							bambooModel);
134 					if (!listModel.contains(obj)) {
135 						listModel.addElement(obj);
136 					}
137 				}
138 				break;
139 			default:
140 				break;
141 		}
142 	}
143 
144 	public static class BambooServerFilter implements BambooBuildFilter {
145 		@NotNull
146 		private final ServerData bambooServerCfg;
147 
148 		public BambooServerFilter(@NotNull final ServerData bambooServerCfg) {
149 			this.bambooServerCfg = bambooServerCfg;
150 		}
151 
152 		@NotNull
153 		public ServerData getBambooServerCfg() {
154 			return bambooServerCfg;
155 		}
156 
157 		public boolean doesMatch(final BambooBuildAdapterIdea build) {
158 			return bambooServerCfg.getServerId().equals(build.getServer().getServerId());
159 		}
160 
161 		@Override
162 		public boolean equals(final Object o) {
163 			if (this == o) {
164 				return true;
165 			}
166 			if (o == null || getClass() != o.getClass()) {
167 				return false;
168 			}
169 
170 			final BambooServerFilter that = (BambooServerFilter) o;
171 
172 			// BambooServerCfg is mutable so we need to base on something immutable
173 			//noinspection RedundantIfStatement
174 			if (!bambooServerCfg.getServerId().equals(that.bambooServerCfg.getServerId())) {
175 				return false;
176 			}
177 
178 			return true;
179 		}
180 
181 		@Override
182 		public int hashCode() {
183 			return bambooServerCfg.getServerId().hashCode();
184 		}
185 	}
186 
187 	private static final BambooBuildFilter ALL_FILTER = new BambooBuildFilter() {
188 		public boolean doesMatch(final BambooBuildAdapterIdea build) {
189 			return true;
190 		}
191 	};
192 
193 
194 	private static class BambooProjectFilter implements BambooBuildFilter {
195 		private final String projectName;
196 
197 		public BambooProjectFilter(final String projectName) {
198 			this.projectName = projectName;
199 		}
200 
201 		public boolean doesMatch(final BambooBuildAdapterIdea build) {
202 			return projectName.equals(build.getProjectName());
203 		}
204 
205 		@Override
206 		public boolean equals(final Object o) {
207 			if (this == o) {
208 				return true;
209 			}
210 			if (o == null || getClass() != o.getClass()) {
211 				return false;
212 			}
213 
214 			final BambooProjectFilter that = (BambooProjectFilter) o;
215 
216 			//noinspection RedundantIfStatement
217 			if (!projectName.equals(that.projectName)) {
218 				return false;
219 			}
220 
221 			return true;
222 		}
223 
224 		@Override
225 		public int hashCode() {
226 			return projectName.hashCode();
227 		}
228 	}
229 
230 
231 	private static class BuildStatusFilter implements BambooBuildFilter {
232 
233 		private final AdjustedBuildStatus status;
234 
235 		public BuildStatusFilter(final AdjustedBuildStatus status) {
236 			this.status = status;
237 		}
238 
239 
240 		public boolean doesMatch(final BambooBuildAdapterIdea build) {
241 			return status == build.getAdjustedStatus();
242 		}
243 
244 		@Override
245 		public boolean equals(final Object o) {
246 			if (this == o) {
247 				return true;
248 			}
249 			if (o == null || getClass() != o.getClass()) {
250 				return false;
251 			}
252 
253 			final BuildStatusFilter that = (BuildStatusFilter) o;
254 
255 			//noinspection RedundantIfStatement
256 			if (status != that.status) {
257 				return false;
258 			}
259 
260 			return true;
261 		}
262 
263 		@Override
264 		public int hashCode() {
265 			return status.hashCode();
266 		}
267 	}
268 
269 	private abstract static class AbstractBambooBuildFilterWrapper<T extends BambooBuildFilter>
270 			extends GenericComboBoxItemWrapper<T> {
271 		private final BuildListModelImpl model;
272 
273 		public AbstractBambooBuildFilterWrapper(final T wrapped, final BuildListModelImpl model) {
274 			super(wrapped);
275 			this.model = model;
276 		}
277 
278 		protected int getCount() {
279 			int i = 0;
280 			for (BambooBuildAdapterIdea build : model.getAllBuilds()) {
281 				if (wrapped.doesMatch(build)) {
282 					i++;
283 				}
284 			}
285 			return i;
286 		}
287 
288 	}
289 
290 	private static class BamboAllFilterWrapper extends AbstractBambooBuildFilterWrapper<BambooBuildFilter> {
291 		public BamboAllFilterWrapper(final BuildListModelImpl model) {
292 			super(ALL_FILTER, model);
293 		}
294 
295 		@Override
296 		public String toString() {
297 			return "All (" + getCount() + ")";
298 		}
299 	}
300 
301 	private static class BamboServerFilterWrapper extends AbstractBambooBuildFilterWrapper<BambooServerFilter> {
302 		public BamboServerFilterWrapper(final BambooServerFilter wrapped, final BuildListModelImpl model) {
303 			super(wrapped, model);
304 		}
305 
306 		public void updateWrapped(BambooServerFilter newWrapped) {
307 			wrapped = newWrapped;
308 		}
309 
310 		@Override
311 		public String toString() {
312 			if (wrapped != null) {
313 				return wrapped.bambooServerCfg.getName() + " (" + getCount() + ")";
314 			}
315 			return "None";
316 		}
317 	}
318 
319 	private static class BamboProjectFilterWrapper extends AbstractBambooBuildFilterWrapper<BambooProjectFilter> {
320 		public BamboProjectFilterWrapper(final BambooProjectFilter wrapped, final BuildListModelImpl model) {
321 			super(wrapped, model);
322 		}
323 
324 		@Override
325 		public String toString() {
326 			if (wrapped != null) {
327 				final String name = (wrapped.projectName == null || wrapped.projectName.length() == 0)
328 						? "Unknown Project" : wrapped.projectName;
329 				return name + " (" + getCount() + ")";
330 			}
331 			return "None";
332 		}
333 	}
334 
335 
336 	private static class BuildStatusFilterWrapper extends AbstractBambooBuildFilterWrapper<BuildStatusFilter> {
337 		public BuildStatusFilterWrapper(final BuildStatusFilter wrapped, final BuildListModelImpl model) {
338 			super(wrapped, model);
339 		}
340 
341 
342 		@Override
343 		public String toString() {
344 			if (wrapped == null) {
345 				return "None";
346 			}
347 			return getString() + " (" + getCount() + ")";
348 		}
349 
350 		private String getString() {
351 			switch (wrapped.status) {
352 				case FAILURE:
353 					return "Build Failed";
354 				case SUCCESS:
355 					return "Build Succeeded";
356 				case UNKNOWN:
357 					return "Unknown State";
358 				case DISABLED:
359 					return "Build Disabled";
360 				default:
361 					return "???";
362 			}
363 		}
364 	}
365 
366 	@Nullable
367 	private BambooBuildFilter getBuildFilter(
368 			@Nullable final Object[] selectedValues) {
369 		if (bambooFilterType == null || selectedValues == null || selectedValues.length == 0) {
370 			return null; // empty filter
371 		}
372 
373 		Collection<BambooBuildFilter> filters = MiscUtil.buildArrayList();
374 		for (Object selectedPath : selectedValues) {
375 			if (selectedPath instanceof AbstractBambooBuildFilterWrapper) {
376 				@SuppressWarnings({"RawUseOfParameterizedType"})
377 				final AbstractBambooBuildFilterWrapper projectBean = (AbstractBambooBuildFilterWrapper) selectedPath;
378 				filters.add((BambooBuildFilter) projectBean.getWrapped());
379 			}
380 		}
381 
382 		return new BambooCompositeOrFilter(filters);
383 	}
384 
385 }