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