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 java.util.ArrayList; 020import java.util.Collection; 021import java.util.Comparator; 022import java.util.HashSet; 023import java.util.LinkedHashSet; 024import java.util.Set; 025import java.util.TreeSet; 026 027import org.forgerock.i18n.LocalizableMessage; 028 029import static org.opends.guitools.controlpanel.util.Utilities.*; 030import static org.opends.messages.AdminToolMessages.*; 031import static org.opends.server.util.CollectionUtils.*; 032 033/** The table model used to display all the database monitoring information. */ 034public class DatabaseMonitoringTableModel extends SortableTableModel implements Comparator<BackendDescriptor> 035{ 036 private static final long serialVersionUID = 548035716525600536L; 037 private Set<BackendDescriptor> data = new HashSet<>(); 038 private ArrayList<String[]> dataArray = new ArrayList<>(); 039 040 private String[] columnNames = {}; 041 private LocalizableMessage NO_VALUE_SET = INFO_CTRL_PANEL_NO_MONITORING_VALUE.get(); 042 private LocalizableMessage NOT_IMPLEMENTED = INFO_CTRL_PANEL_NOT_IMPLEMENTED.get(); 043 044 /** The fields to be displayed. */ 045 private LinkedHashSet<String> attributes = new LinkedHashSet<>(); 046 /** The sort column of the table. */ 047 private int sortColumn; 048 /** Whether the sorting is ascending or descending. */ 049 private boolean sortAscending = true; 050 051 /** 052 * Sets the data for this table model. 053 * @param newData the data for this table model. 054 */ 055 public void setData(Set<BackendDescriptor> newData) 056 { 057 if (!newData.equals(data)) 058 { 059 data.clear(); 060 data.addAll(newData); 061 updateDataArray(); 062 fireTableDataChanged(); 063 } 064 } 065 066 /** 067 * Updates the table model contents and sorts its contents depending on the 068 * sort options set by the user. 069 */ 070 @Override 071 public void forceResort() 072 { 073 updateDataArray(); 074 fireTableDataChanged(); 075 } 076 077 /** 078 * Updates the table model contents, sorts its contents depending on the 079 * sort options set by the user and updates the column structure. 080 */ 081 public void forceDataStructureChange() 082 { 083 updateDataArray(); 084 fireTableStructureChanged(); 085 fireTableDataChanged(); 086 } 087 088 /** {@inheritDoc} */ 089 @Override 090 public int getColumnCount() 091 { 092 return columnNames.length; 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public int getRowCount() 098 { 099 return dataArray.size(); 100 } 101 102 /** {@inheritDoc} */ 103 @Override 104 public Object getValueAt(int row, int col) 105 { 106 return dataArray.get(row)[col]; 107 } 108 109 /** {@inheritDoc} */ 110 @Override 111 public String getColumnName(int col) { 112 return columnNames[col]; 113 } 114 115 /** {@inheritDoc} */ 116 @Override 117 public int compare(BackendDescriptor desc1, BackendDescriptor desc2) 118 { 119 CustomSearchResult monitor1 = desc1.getMonitoringEntry(); 120 CustomSearchResult monitor2 = desc2.getMonitoringEntry(); 121 122 ArrayList<Integer> possibleResults = newArrayList(getName(desc1).compareTo(getName(desc2))); 123 computeMonitoringPossibleResults(monitor1, monitor2, possibleResults, attributes); 124 125 int result = possibleResults.get(getSortColumn()); 126 if (result == 0) 127 { 128 result = getFirstNonZero(possibleResults); 129 } 130 if (!isSortAscending()) 131 { 132 result = -result; 133 } 134 return result; 135 } 136 137 private int getFirstNonZero(ArrayList<Integer> possibleResults) 138 { 139 for (int i : possibleResults) 140 { 141 if (i != 0) 142 { 143 return i; 144 } 145 } 146 return 0; 147 } 148 149 /** 150 * Returns whether the sort is ascending or descending. 151 * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE> 152 * otherwise. 153 */ 154 @Override 155 public boolean isSortAscending() 156 { 157 return sortAscending; 158 } 159 160 /** 161 * Sets whether to sort ascending of descending. 162 * @param sortAscending whether to sort ascending or descending. 163 */ 164 @Override 165 public void setSortAscending(boolean sortAscending) 166 { 167 this.sortAscending = sortAscending; 168 } 169 170 /** 171 * Returns the column index used to sort. 172 * @return the column index used to sort. 173 */ 174 @Override 175 public int getSortColumn() 176 { 177 return sortColumn; 178 } 179 180 /** 181 * Sets the column index used to sort. 182 * @param sortColumn column index used to sort.. 183 */ 184 @Override 185 public void setSortColumn(int sortColumn) 186 { 187 this.sortColumn = sortColumn; 188 } 189 190 /** 191 * Returns the fields displayed by this table model. 192 * @return the fields displayed by this table model. 193 */ 194 public Collection<String> getAttributes() 195 { 196 return attributes; 197 } 198 199 /** 200 * Sets the fields displayed by this table model. 201 * @param fields the statistic fields displayed by this table model. 202 */ 203 public void setAttributes(LinkedHashSet<String> fields) 204 { 205 this.attributes.clear(); 206 this.attributes.addAll(fields); 207 columnNames = new String[fields.size() + 1]; 208 columnNames[0] = INFO_CTRL_PANEL_DB_HEADER.get().toString(); 209 int i = 1; 210 for (String field : fields) 211 { 212 columnNames[i] = field; 213 i++; 214 } 215 } 216 217 /** 218 * Updates the array data. This includes resorting it. 219 */ 220 private void updateDataArray() 221 { 222 TreeSet<BackendDescriptor> sortedSet = new TreeSet<>(this); 223 sortedSet.addAll(data); 224 dataArray.clear(); 225 for (BackendDescriptor ach : sortedSet) 226 { 227 String[] s = getLine(ach); 228 dataArray.add(s); 229 } 230 231 // Add the total: always at the end 232 233 String[] line = new String[attributes.size() + 1]; 234 line[0] = "<html><b>" + INFO_CTRL_PANEL_TOTAL_LABEL.get() + "</b>"; 235 for (int i=1; i<line.length; i++) 236 { 237 boolean valueSet = false; 238 boolean notImplemented = false; 239 long totalValue = 0; 240 for (String[] l : dataArray) 241 { 242 String value = l[i]; 243 try 244 { 245 long v = Long.parseLong(value); 246 totalValue += v; 247 valueSet = true; 248 } 249 catch (Throwable t) 250 { 251 try 252 { 253 double v = Double.parseDouble(value); 254 totalValue += v; 255 valueSet = true; 256 } 257 catch (Throwable t2) 258 { 259 notImplemented = NOT_IMPLEMENTED.toString().equals(value); 260 } 261 } 262 } 263 if (notImplemented) 264 { 265 line[i] = NOT_IMPLEMENTED.toString(); 266 } 267 else if (valueSet) 268 { 269 line[i] = String.valueOf(totalValue); 270 } 271 else 272 { 273 line[i] = NO_VALUE_SET.toString(); 274 } 275 } 276 dataArray.add(line); 277 } 278 279 /** 280 * Returns the label to be used for the provided backend. 281 * @param backend the backend. 282 * @return the label to be used for the provided backend. 283 */ 284 protected String getName(BackendDescriptor backend) 285 { 286 return backend.getBackendID(); 287 } 288 289 /** 290 * Returns the monitoring entry associated with the provided backend. 291 * @param backend the backend. 292 * @return the monitoring entry associated with the provided backend. Returns 293 * <CODE>null</CODE> if there is no monitoring entry associated. 294 */ 295 protected CustomSearchResult getMonitoringEntry(BackendDescriptor backend) 296 { 297 return backend.getMonitoringEntry(); 298 } 299 300 private String[] getLine(BackendDescriptor backend) 301 { 302 String[] line = new String[attributes.size() + 1]; 303 line[0] = getName(backend); 304 int i = 1; 305 CustomSearchResult monitoringEntry = getMonitoringEntry(backend); 306 for (String attr : attributes) 307 { 308 String o = getFirstValueAsString(monitoringEntry, attr); 309 if (o != null) 310 { 311 line[i] = o; 312 } 313 else 314 { 315 line[i] = NO_VALUE_SET.toString(); 316 } 317 i++; 318 } 319 return line; 320 } 321 322}