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