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