001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.guitools.controlpanel.datamodel; 028 029import static org.forgerock.util.Utils.*; 030import static org.opends.messages.AdminToolMessages.*; 031import static org.opends.messages.ToolMessages.*; 032 033import java.util.ArrayList; 034import java.util.Comparator; 035import java.util.HashSet; 036import java.util.LinkedHashSet; 037import java.util.List; 038import java.util.Set; 039import java.util.TreeSet; 040 041import org.opends.guitools.controlpanel.ui.ColorAndFontConstants; 042import org.opends.guitools.controlpanel.util.Utilities; 043import org.forgerock.i18n.LocalizableMessage; 044import org.opends.server.backends.task.TaskState; 045import org.opends.server.tools.tasks.TaskEntry; 046 047/** 048 * The table used to display the tasks. 049 * 050 */ 051public class TaskTableModel extends SortableTableModel 052implements Comparator<TaskEntry> 053{ 054 private static final long serialVersionUID = -351142550147124L; 055 private Set<TaskEntry> data = new HashSet<>(); 056 private ArrayList<TaskEntry> dataSourceArray = new ArrayList<>(); 057 058 LinkedHashSet<LocalizableMessage> displayedAttributes = new LinkedHashSet<>(); 059 final LinkedHashSet<LocalizableMessage> defaultAttributes = new LinkedHashSet<>(); 060 { 061 defaultAttributes.add(INFO_TASKINFO_FIELD_ID.get()); 062 defaultAttributes.add(INFO_TASKINFO_FIELD_TYPE.get()); 063 defaultAttributes.add(INFO_TASKINFO_FIELD_STATUS.get()); 064 defaultAttributes.add(INFO_CTRL_PANEL_TASK_CANCELABLE.get()); 065 } 066 LinkedHashSet<LocalizableMessage> allAttributes = new LinkedHashSet<>(); 067 { 068 allAttributes.addAll(defaultAttributes); 069 allAttributes.add(INFO_TASKINFO_FIELD_SCHEDULED_START.get()); 070 allAttributes.add(INFO_TASKINFO_FIELD_ACTUAL_START.get()); 071 allAttributes.add(INFO_TASKINFO_FIELD_COMPLETION_TIME.get()); 072 allAttributes.add(INFO_TASKINFO_FIELD_DEPENDENCY.get()); 073 allAttributes.add(INFO_TASKINFO_FIELD_FAILED_DEPENDENCY_ACTION.get()); 074 allAttributes.add(INFO_TASKINFO_FIELD_NOTIFY_ON_COMPLETION.get()); 075 allAttributes.add(INFO_TASKINFO_FIELD_NOTIFY_ON_ERROR.get()); 076 } 077 078 private String[] columnNames = {}; 079 080 /** 081 * The sort column of the table. 082 */ 083 private int sortColumn; 084 /** 085 * Whether the sorting is ascending or descending. 086 */ 087 private boolean sortAscending = true; 088 089 /** 090 * Default constructor. 091 */ 092 public TaskTableModel() 093 { 094 super(); 095 setAttributes(defaultAttributes); 096 } 097 098 /** 099 * Sets the data for this table model. 100 * @param newData the data for this table model. 101 */ 102 public void setData(Set<TaskEntry> newData) 103 { 104 if (!newData.equals(data)) 105 { 106 data.clear(); 107 data.addAll(newData); 108 updateDataArray(); 109 fireTableDataChanged(); 110 } 111 } 112 113 /** 114 * Updates the table model contents and sorts its contents depending on the 115 * sort options set by the user. 116 */ 117 public void forceResort() 118 { 119 updateDataArray(); 120 fireTableDataChanged(); 121 } 122 123 /** 124 * Updates the table model contents, sorts its contents depending on the 125 * sort options set by the user and updates the column structure. 126 */ 127 public void forceDataStructureChange() 128 { 129 updateDataArray(); 130 fireTableStructureChanged(); 131 fireTableDataChanged(); 132 } 133 134 /** 135 * Updates the array data. This includes resorting it. 136 */ 137 private void updateDataArray() 138 { 139 TreeSet<TaskEntry> sortedSet = new TreeSet<>(this); 140 sortedSet.addAll(data); 141 dataSourceArray.clear(); 142 dataSourceArray.addAll(sortedSet); 143 } 144 145 /** 146 * Sets the operations displayed by this table model. 147 * @param attributes the attributes displayed by this table model. 148 */ 149 public void setAttributes(LinkedHashSet<LocalizableMessage> attributes) 150 { 151 if (!allAttributes.containsAll(attributes)) 152 { 153 throw new IllegalArgumentException( 154 "Some of the provided attributes are not valid."); 155 } 156 this.displayedAttributes.clear(); 157 this.displayedAttributes.addAll(attributes); 158 int columnCount = attributes.size(); 159 columnNames = new String[columnCount]; 160 int i = 0; 161 for (LocalizableMessage attribute : attributes) 162 { 163 columnNames[i] = getHeader(attribute, 15); 164 i++; 165 } 166 } 167 168 /** {@inheritDoc} */ 169 public Class<?> getColumnClass(int column) 170 { 171 return LocalizableMessage.class; 172 } 173 174 /** {@inheritDoc} */ 175 public String getColumnName(int col) { 176 return columnNames[col]; 177 } 178 179 /** {@inheritDoc} */ 180 public Object getValueAt(int row, int column) 181 { 182 LocalizableMessage value; 183 column = getFixedOrderColumn(column); 184 TaskEntry taskEntry = get(row); 185 switch (column) 186 { 187 case 0: 188 return LocalizableMessage.raw(taskEntry.getId()); 189 case 1: 190 return taskEntry.getType(); 191 case 2: 192 return taskEntry.getState(); 193 case 3: 194 return taskEntry.isCancelable() 195 ? INFO_CTRL_PANEL_TASK_IS_CANCELABLE.get() 196 : INFO_CTRL_PANEL_TASK_IS_NOT_CANCELABLE.get(); 197 case 4: 198 if (TaskState.isRecurring(get(row).getTaskState())) 199 { 200 return taskEntry.getScheduleTab(); 201 } 202 203 value = taskEntry.getScheduledStartTime(); 204 if (value == null || value.equals(LocalizableMessage.EMPTY)) 205 { 206 return INFO_TASKINFO_IMMEDIATE_EXECUTION.get(); 207 } 208 return value; 209 case 5: 210 return taskEntry.getActualStartTime(); 211 case 6: 212 return taskEntry.getCompletionTime(); 213 case 7: 214 return getValue(taskEntry.getDependencyIds(), 215 INFO_TASKINFO_NONE_SPECIFIED.get()); 216 case 8: 217 value = taskEntry.getFailedDependencyAction(); 218 if (value != null) 219 { 220 return value; 221 } 222 return INFO_TASKINFO_NONE.get(); 223 case 9: 224 return getValue(taskEntry.getCompletionNotificationEmailAddresses(), 225 INFO_TASKINFO_NONE_SPECIFIED.get()); 226 case 10: 227 return getValue(taskEntry.getErrorNotificationEmailAddresses(), 228 INFO_TASKINFO_NONE_SPECIFIED.get()); 229 default: 230 throw new IllegalArgumentException("Invalid column: "+column); 231 } 232 } 233 234 /** 235 * Returns the row count. 236 * @return the row count. 237 */ 238 public int getRowCount() 239 { 240 return dataSourceArray.size(); 241 } 242 243 /** 244 * Returns the column count. 245 * @return the column count. 246 */ 247 public int getColumnCount() 248 { 249 return columnNames.length; 250 } 251 252 /** 253 * Gets the TaskDescriptor in a given row. 254 * @param row the row. 255 * @return the TaskDescriptor in a given row. 256 */ 257 public TaskEntry get(int row) 258 { 259 return dataSourceArray.get(row); 260 } 261 262 /** 263 * Returns the set of attributes ordered. 264 * @return the set of attributes ordered. 265 */ 266 public LinkedHashSet<LocalizableMessage> getDisplayedAttributes() 267 { 268 return displayedAttributes; 269 } 270 271 /** 272 * Returns the set of attributes ordered. 273 * @return the set of attributes ordered. 274 */ 275 public LinkedHashSet<LocalizableMessage> getAllAttributes() 276 { 277 return allAttributes; 278 } 279 280 /** {@inheritDoc} */ 281 public int compare(TaskEntry desc1, TaskEntry desc2) 282 { 283 int result; 284 ArrayList<Integer> possibleResults = new ArrayList<>(); 285 286 possibleResults.add(desc1.getId().compareTo(desc2.getId())); 287 possibleResults.add(desc1.getType().compareTo(desc2.getType())); 288 possibleResults.add(desc1.getState().compareTo(desc2.getState())); 289 possibleResults.add(String.valueOf(desc1.isCancelable()).compareTo( 290 String.valueOf(desc2.isCancelable()))); 291 292 result = possibleResults.get(getSortColumn()); 293 if (result == 0) 294 { 295 for (int i : possibleResults) 296 { 297 if (i != 0) 298 { 299 result = i; 300 break; 301 } 302 } 303 } 304 if (!isSortAscending()) 305 { 306 result = -result; 307 } 308 return result; 309 } 310 311 /** 312 * Returns whether the sort is ascending or descending. 313 * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE> 314 * otherwise. 315 */ 316 public boolean isSortAscending() 317 { 318 return sortAscending; 319 } 320 321 /** 322 * Sets whether to sort ascending of descending. 323 * @param sortAscending whether to sort ascending or descending. 324 */ 325 public void setSortAscending(boolean sortAscending) 326 { 327 this.sortAscending = sortAscending; 328 } 329 330 /** 331 * Returns the column index used to sort. 332 * @return the column index used to sort. 333 */ 334 public int getSortColumn() 335 { 336 return sortColumn; 337 } 338 339 /** 340 * Sets the column index used to sort. 341 * @param sortColumn column index used to sort.. 342 */ 343 public void setSortColumn(int sortColumn) 344 { 345 this.sortColumn = sortColumn; 346 } 347 348 private int getFixedOrderColumn(int column) 349 { 350 int fixedOrderColumn = 0; 351 int i=0; 352 LocalizableMessage colMsg = null; 353 for (LocalizableMessage msg : displayedAttributes) 354 { 355 if (i == column) 356 { 357 colMsg = msg; 358 break; 359 } 360 i++; 361 } 362 for (LocalizableMessage msg : allAttributes) 363 { 364 if (msg.equals(colMsg)) 365 { 366 break; 367 } 368 fixedOrderColumn++; 369 } 370 return fixedOrderColumn; 371 } 372 373 private LocalizableMessage getValue(List<String> values, LocalizableMessage valueIfEmpty) 374 { 375 LocalizableMessage msg; 376 if (values.isEmpty()) 377 { 378 msg = valueIfEmpty; 379 } 380 else 381 { 382 String s = joinAsString("<br>", values); 383 if (values.size() > 1) 384 { 385 msg = LocalizableMessage.raw( 386 "<html>"+Utilities.applyFont(s, ColorAndFontConstants.tableFont)); 387 } 388 else 389 { 390 msg = LocalizableMessage.raw(s); 391 } 392 } 393 return msg; 394 } 395}