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}