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