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 2008 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017 018package org.opends.guitools.controlpanel.datamodel; 019 020import static org.opends.messages.AdminToolMessages.*; 021 022import java.util.ArrayList; 023import java.util.Comparator; 024import java.util.Date; 025import java.util.HashSet; 026import java.util.Set; 027import java.util.TreeSet; 028 029import org.opends.guitools.controlpanel.util.Utilities; 030import org.forgerock.i18n.LocalizableMessage; 031 032/** The table model used to display all the base DNs. */ 033public class BaseDNTableModel extends SortableTableModel 034implements Comparator<BaseDNDescriptor> 035{ 036 private static final long serialVersionUID = -5650762484071136983L; 037 private HashSet<BaseDNDescriptor> data = new HashSet<>(); 038 private ServerDescriptor.ServerStatus serverStatus; 039 private boolean isAuthenticated; 040 041 private ArrayList<String[]> dataArray = new ArrayList<>(); 042 private String[] COLUMN_NAMES; 043 private int sortColumn; 044 private boolean sortAscending = true; 045 private boolean displayReplicationInformation; 046 047 /** Key value to identify the case of a value not available because the server is down. */ 048 public static String NOT_AVAILABLE_SERVER_DOWN = "NOT_AVAILABLE_SERVER_DOWN"; 049 050 /** Key value to identify the case of a value not available because authentication is required. */ 051 public static String NOT_AVAILABLE_AUTHENTICATION_REQUIRED = 052 "NOT_AVAILABLE_AUTHENTICATION_REQUIRED"; 053 054 /** Key value to identify the case of a value not available. */ 055 public static String NOT_AVAILABLE = "NOT_AVAILABLE"; 056 057 /** 058 * Constructor for this table model. 059 * @param displayReplicationInformation whether to display replication. 060 * monitoring information or not. 061 */ 062 public BaseDNTableModel(boolean displayReplicationInformation) 063 { 064 this(displayReplicationInformation, true); 065 } 066 067 /** 068 * Constructor for this table model. 069 * @param displayReplicationInformation whether to display replication. 070 * @param wrapHeader whether to wrap the headers or not. 071 * monitoring information or not. 072 */ 073 public BaseDNTableModel(boolean displayReplicationInformation, 074 boolean wrapHeader) 075 { 076 this.displayReplicationInformation = displayReplicationInformation; 077 if (wrapHeader) 078 { 079 COLUMN_NAMES = new String[] { 080 getHeader(INFO_BASEDN_COLUMN.get()), 081 getHeader(INFO_BACKENDID_COLUMN.get()), 082 getHeader(INFO_NUMBER_ENTRIES_COLUMN.get()), 083 getHeader(INFO_REPLICATED_COLUMN.get()), 084 getHeader(INFO_MISSING_CHANGES_COLUMN.get()), 085 getHeader(INFO_AGE_OF_OLDEST_MISSING_CHANGE_COLUMN.get()) 086 }; 087 } 088 else 089 { 090 COLUMN_NAMES = new String[] { 091 INFO_BASEDN_COLUMN.get().toString(), 092 INFO_BACKENDID_COLUMN.get().toString(), 093 INFO_NUMBER_ENTRIES_COLUMN.get().toString(), 094 INFO_REPLICATED_COLUMN.get().toString(), 095 INFO_MISSING_CHANGES_COLUMN.get().toString(), 096 INFO_AGE_OF_OLDEST_MISSING_CHANGE_COLUMN.get().toString() 097 }; 098 } 099 } 100 101 /** 102 * Sets the data for this table model. 103 * @param newData the data for this table model. 104 * @param status the server status. 105 * @param isAuthenticated whether the user provided authentication or not. 106 */ 107 public void setData(Set<BaseDNDescriptor> newData, 108 ServerDescriptor.ServerStatus status, boolean isAuthenticated) 109 { 110 if (!newData.equals(data) || serverStatus != status || this.isAuthenticated != isAuthenticated) 111 { 112 serverStatus = status; 113 this.isAuthenticated = isAuthenticated; 114 data.clear(); 115 data.addAll(newData); 116 updateDataArray(); 117 fireTableDataChanged(); 118 } 119 } 120 121 /** 122 * Updates the table model contents and sorts its contents depending on the 123 * sort options set by the user. 124 */ 125 @Override 126 public void forceResort() 127 { 128 updateDataArray(); 129 fireTableDataChanged(); 130 } 131 132 /** 133 * Comparable implementation. 134 * @param desc1 the first replica descriptor to compare. 135 * @param desc2 the second replica descriptor to compare. 136 * @return 1 if according to the sorting options set by the user the first 137 * base DN descriptor must be put before the second descriptor, 0 if they 138 * are equivalent in terms of sorting and -1 if the second descriptor must 139 * be put before the first descriptor. 140 */ 141 @Override 142 public int compare(BaseDNDescriptor desc1, BaseDNDescriptor desc2) 143 { 144 int result = 0; 145 if (sortColumn == 0) 146 { 147 result = compareDns(desc1, desc2); 148 149 if (result == 0) 150 { 151 result = compareBackendIDs(desc1, desc2); 152 } 153 154 if (result == 0) 155 { 156 result = compareEntries(desc1, desc2); 157 } 158 159 if (result == 0) 160 { 161 result = compareRepl(desc1, desc2); 162 } 163 164 if (result == 0) 165 { 166 result = compareMissingChanges(desc1, desc2); 167 } 168 169 if (result == 0) 170 { 171 result = compareAgeOfOldestMissingChange(desc1, desc2); 172 } 173 } 174 175 if (sortColumn == 1) 176 { 177 result = compareBackendIDs(desc1, desc2); 178 179 if (result == 0) 180 { 181 result = compareDns(desc1, desc2); 182 183 } 184 185 if (result == 0) 186 { 187 result = compareEntries(desc1, desc2); 188 } 189 190 if (result == 0) 191 { 192 result = compareRepl(desc1, desc2); 193 } 194 195 if (result == 0) 196 { 197 result = compareMissingChanges(desc1, desc2); 198 } 199 200 if (result == 0) 201 { 202 result = compareAgeOfOldestMissingChange(desc1, desc2); 203 } 204 } 205 else if (sortColumn == 2) 206 { 207 result = compareEntries(desc1, desc2); 208 209 if (result == 0) 210 { 211 result = compareBackendIDs(desc1, desc2); 212 } 213 214 if (result == 0) 215 { 216 result = compareDns(desc1, desc2); 217 } 218 219 if (result == 0) 220 { 221 result = compareRepl(desc1, desc2); 222 } 223 224 if (result == 0) 225 { 226 result = compareMissingChanges(desc1, desc2); 227 } 228 229 if (result == 0) 230 { 231 result = compareAgeOfOldestMissingChange(desc1, desc2); 232 } 233 } 234 else if (sortColumn == 3) 235 { 236 result = compareRepl(desc1, desc2); 237 238 if (result == 0) 239 { 240 result = compareBackendIDs(desc1, desc2); 241 } 242 243 if (result == 0) 244 { 245 result = compareDns(desc1, desc2); 246 } 247 248 if (result == 0) 249 { 250 result = compareEntries(desc1, desc2); 251 } 252 253 if (result == 0) 254 { 255 result = compareMissingChanges(desc1, desc2); 256 } 257 258 if (result == 0) 259 { 260 result = compareAgeOfOldestMissingChange(desc1, desc2); 261 } 262 } 263 else if (sortColumn == 4) 264 { 265 result = compareMissingChanges(desc1, desc2); 266 267 if (result == 0) 268 { 269 result = compareBackendIDs(desc1, desc2); 270 } 271 272 if (result == 0) 273 { 274 result = compareDns(desc1, desc2); 275 } 276 277 if (result == 0) 278 { 279 result = compareEntries(desc1, desc2); 280 } 281 282 if (result == 0) 283 { 284 result = compareRepl(desc1, desc2); 285 } 286 287 if (result == 0) 288 { 289 result = compareAgeOfOldestMissingChange(desc1, desc2); 290 } 291 } 292 else if (sortColumn == 5) 293 { 294 result = compareAgeOfOldestMissingChange(desc1, desc2); 295 296 if (result == 0) 297 { 298 result = compareBackendIDs(desc1, desc2); 299 } 300 301 if (result == 0) 302 { 303 result = compareDns(desc1, desc2); 304 } 305 306 if (result == 0) 307 { 308 result = compareEntries(desc1, desc2); 309 } 310 311 if (result == 0) 312 { 313 result = compareRepl(desc1, desc2); 314 } 315 316 if (result == 0) 317 { 318 result = compareMissingChanges(desc1, desc2); 319 } 320 } 321 322 if (!sortAscending) 323 { 324 result = -result; 325 } 326 327 return result; 328 } 329 330 @Override 331 public int getColumnCount() 332 { 333 return displayReplicationInformation ? 6 : 4; 334 } 335 336 @Override 337 public int getRowCount() 338 { 339 return dataArray.size(); 340 } 341 342 @Override 343 public Object getValueAt(int row, int col) 344 { 345 return dataArray.get(row)[col]; 346 } 347 348 /** Updates the array data. This includes resorting it. */ 349 private void updateDataArray() 350 { 351 TreeSet<BaseDNDescriptor> sortedSet = new TreeSet<>(this); 352 sortedSet.addAll(data); 353 dataArray.clear(); 354 for (BaseDNDescriptor desc : sortedSet) 355 { 356 dataArray.add(new String[] { 357 Utilities.unescapeUtf8(desc.getDn().toString()), 358 desc.getBackend().getBackendID(), 359 getValueForEntries(desc), 360 getStringForReplState(desc), 361 getValueForMissingChanges(desc), 362 getValueForOldestMissingChange(desc) 363 }); 364 } 365 } 366 367 @Override 368 public String getColumnName(int col) { 369 return COLUMN_NAMES[col]; 370 } 371 372 @Override 373 public boolean isSortAscending() 374 { 375 return sortAscending; 376 } 377 378 @Override 379 public void setSortAscending(boolean sortAscending) 380 { 381 this.sortAscending = sortAscending; 382 } 383 384 @Override 385 public int getSortColumn() 386 { 387 return sortColumn; 388 } 389 390 @Override 391 public void setSortColumn(int sortColumn) 392 { 393 this.sortColumn = sortColumn; 394 } 395 396 /** Several comparison methods to be able to sort the table model. */ 397 private int compareBackendIDs(BaseDNDescriptor desc1, BaseDNDescriptor desc2) 398 { 399 return desc1.getBackend().getBackendID().compareTo( 400 desc2.getBackend().getBackendID()); 401 } 402 403 private int compareEntries(BaseDNDescriptor desc1, BaseDNDescriptor desc2) 404 { 405 int n1 = desc1.getEntries(); 406 int n2 = desc2.getEntries(); 407 return compareIntegers(n1, n2); 408 } 409 410 private int compareIntegers(int n1, int n2) 411 { 412 if (n1 == n2) 413 { 414 return 0; 415 } 416 if (n1 > n2) 417 { 418 return 1; 419 } 420 return -1; 421 } 422 423 private int compareLongs(long n1, long n2) 424 { 425 if (n1 == n2) 426 { 427 return 0; 428 } 429 if (n1 > n2) 430 { 431 return 1; 432 } 433 return -1; 434 } 435 436 private int compareDns(BaseDNDescriptor desc1, BaseDNDescriptor desc2) 437 { 438 return Utilities.unescapeUtf8(desc1.getDn().toString()).compareTo( 439 Utilities.unescapeUtf8(desc2.getDn().toString())); 440 } 441 442 private int compareRepl(BaseDNDescriptor desc1, BaseDNDescriptor desc2) 443 { 444 String val1 = String.valueOf(desc1.getType()); 445 String val2 = String.valueOf(desc2.getType()); 446 return val1.compareTo(val2); 447 } 448 449 private int compareMissingChanges(BaseDNDescriptor desc1, 450 BaseDNDescriptor desc2) 451 { 452 return compareIntegers(desc1.getMissingChanges(), 453 desc2.getMissingChanges()); 454 } 455 456 private int compareAgeOfOldestMissingChange(BaseDNDescriptor desc1, 457 BaseDNDescriptor desc2) 458 { 459 return compareLongs(desc1.getAgeOfOldestMissingChange(), 460 desc2.getAgeOfOldestMissingChange()); 461 } 462 463 /** 464 * Returns the Object describing the number of entries of a given Base DN. 465 * The Object will be an Integer. 466 * @param rep the Base DN object to handle. 467 * @return the Object describing the number of entries of a given Base DN. 468 */ 469 private String getValueForEntries(BaseDNDescriptor rep) 470 { 471 String returnValue; 472 if (serverStatus != ServerDescriptor.ServerStatus.STARTED) 473 { 474 returnValue = NOT_AVAILABLE_SERVER_DOWN; 475 } 476 else if (!isAuthenticated) 477 { 478 returnValue = NOT_AVAILABLE_AUTHENTICATION_REQUIRED; 479 } 480 else 481 { 482 if (rep.getEntries() < 0) 483 { 484 returnValue = NOT_AVAILABLE; 485 } 486 else 487 { 488 returnValue = String.valueOf(rep.getEntries()); 489 } 490 } 491 return returnValue; 492 } 493 494 /** 495 * Returns the Object describing the number of missing changes of a given Base 496 * DN. The Object will be a String unless the base DN is 497 * replicated and we could not find a valid value (in this case we return 498 * an Integer with the invalid value). 499 * @param rep the Base DN object to handle. 500 * @return the Object describing the number of missing changes of 501 * a given Base DN. 502 */ 503 private String getValueForMissingChanges(BaseDNDescriptor rep) 504 { 505 String returnValue; 506 if (rep.getType() == BaseDNDescriptor.Type.REPLICATED) 507 { 508 if (serverStatus != ServerDescriptor.ServerStatus.STARTED) 509 { 510 returnValue = NOT_AVAILABLE_SERVER_DOWN; 511 } 512 else if (!isAuthenticated) 513 { 514 returnValue = NOT_AVAILABLE_AUTHENTICATION_REQUIRED; 515 } 516 else 517 { 518 if (rep.getMissingChanges() < 0) 519 { 520 returnValue = NOT_AVAILABLE; 521 } 522 else 523 { 524 returnValue = String.valueOf(rep.getMissingChanges()); 525 } 526 } 527 } 528 else 529 { 530 returnValue = INFO_NOT_APPLICABLE_LABEL.get().toString(); 531 } 532 return returnValue; 533 } 534 535 /** 536 * Returns the Object describing the age of oldest missing change of 537 * a given Base DN. The Object will be a String unless the base DN is 538 * replicated and we could not find a valid value (in this case we return 539 * an Integer with the invalid value). 540 * @param rep the Base DN object to handle. 541 * @return the Object describing the age of oldest missing change of 542 * a given Base DN. 543 */ 544 private String getValueForOldestMissingChange(BaseDNDescriptor rep) 545 { 546 String returnValue; 547 if (rep.getType() == BaseDNDescriptor.Type.REPLICATED) 548 { 549 if (serverStatus != ServerDescriptor.ServerStatus.STARTED) 550 { 551 returnValue = NOT_AVAILABLE_SERVER_DOWN; 552 } 553 else if (!isAuthenticated) 554 { 555 returnValue = NOT_AVAILABLE_AUTHENTICATION_REQUIRED; 556 } 557 else 558 { 559 long age = rep.getAgeOfOldestMissingChange(); 560 if (age > 0) 561 { 562 Date date = new Date(age); 563 returnValue = date.toString(); 564 } 565 else 566 { 567 // Not available 568 returnValue = NOT_AVAILABLE; 569 } 570 } 571 } 572 else 573 { 574 returnValue = INFO_NOT_APPLICABLE_LABEL.get().toString(); 575 } 576 return returnValue; 577 } 578 579 /** 580 * Returns the localized String describing the replication state of 581 * a given Base DN. 582 * @param rep the Base DN object to handle. 583 * @return the localized String describing the replication state of 584 * a given Base DN. 585 */ 586 private String getStringForReplState(BaseDNDescriptor rep) 587 { 588 LocalizableMessage s; 589 if (rep.getType() == BaseDNDescriptor.Type.REPLICATED) 590 { 591 s = INFO_BASEDN_REPLICATED_LABEL.get(); 592 } 593 else if (rep.getType() == BaseDNDescriptor.Type.NOT_REPLICATED) 594 { 595 s = INFO_BASEDN_NOT_REPLICATED_LABEL.get(); 596 } 597 else 598 { 599 s = INFO_BASEDN_DISABLED_LABEL.get(); 600 } 601 return s.toString(); 602 } 603}