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