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