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}