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-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.guitools.controlpanel.ui; 028 029import static org.opends.messages.AdminToolMessages.*; 030 031import java.awt.Component; 032import java.awt.GridBagConstraints; 033import java.awt.GridBagLayout; 034import java.awt.Insets; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037import java.util.ArrayList; 038import java.util.Collection; 039import java.util.HashSet; 040import java.util.List; 041import java.util.Set; 042import java.util.SortedSet; 043import java.util.TreeSet; 044 045import javax.naming.ldap.InitialLdapContext; 046import javax.swing.Box; 047import javax.swing.JCheckBox; 048import javax.swing.JComponent; 049import javax.swing.JPanel; 050import javax.swing.JScrollPane; 051import javax.swing.SwingConstants; 052import javax.swing.SwingUtilities; 053import javax.swing.border.EmptyBorder; 054import javax.swing.event.DocumentEvent; 055import javax.swing.event.DocumentListener; 056 057import org.forgerock.i18n.LocalizableMessage; 058import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; 059import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 060import org.opends.guitools.controlpanel.datamodel.IndexDescriptor; 061import org.opends.guitools.controlpanel.datamodel.IndexTypeDescriptor; 062import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 063import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 064import org.opends.guitools.controlpanel.event.ScrollPaneBorderListener; 065import org.opends.guitools.controlpanel.task.DeleteIndexTask; 066import org.opends.guitools.controlpanel.task.Task; 067import org.opends.guitools.controlpanel.util.ConfigReader; 068import org.opends.guitools.controlpanel.util.Utilities; 069import org.opends.server.admin.client.ManagementContext; 070import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor; 071import org.opends.server.admin.client.ldap.LDAPManagementContext; 072import org.opends.server.admin.std.client.BackendCfgClient; 073import org.opends.server.admin.std.client.BackendIndexCfgClient; 074import org.opends.server.admin.std.client.PluggableBackendCfgClient; 075import org.opends.server.core.DirectoryServer; 076import org.opends.server.types.AttributeType; 077import org.opends.server.types.DN; 078import org.opends.server.types.OpenDsException; 079 080/** 081 * The panel that displays an existing index (it appears on the right of the 082 * 'Manage Indexes' dialog). 083 */ 084public class IndexPanel extends AbstractIndexPanel 085{ 086 private static final long serialVersionUID = 1439500626486823366L; 087 088 private IndexDescriptor index; 089 private ScrollPaneBorderListener scrollListener; 090 091 private boolean ignoreCheckSave; 092 093 private ModifyIndexTask newModifyTask; 094 095 /** Default constructor. */ 096 public IndexPanel() 097 { 098 super(); 099 createLayout(); 100 } 101 102 /** 103 * Creates the layout of the panel (but the contents are not populated here). 104 */ 105 private void createLayout() 106 { 107 GridBagConstraints gbc = new GridBagConstraints(); 108 JPanel p = new JPanel(new GridBagLayout()); 109 p.setOpaque(false); 110 super.createBasicLayout(p, gbc, true); 111 p.setBorder(new EmptyBorder(10, 10, 10, 10)); 112 gbc = new GridBagConstraints(); 113 gbc.weightx = 1.0; 114 gbc.weighty = 1.0; 115 gbc.fill = GridBagConstraints.BOTH; 116 gbc.gridx = 0; 117 gbc.gridy = 0; 118 JScrollPane scroll = Utilities.createBorderLessScrollBar(p); 119 scrollListener = 120 ScrollPaneBorderListener.createBottomBorderListener(scroll); 121 add(scroll, gbc); 122 123 gbc.gridy ++; 124 gbc.gridx = 0; 125 gbc.weightx = 1.0; 126 gbc.insets.left = 0; 127 gbc.gridwidth = 2; 128 gbc.weighty = 0.0; 129 gbc.fill = GridBagConstraints.HORIZONTAL; 130 131 gbc.insets = new Insets(10, 10, 0, 10); 132 add(warning, gbc); 133 Utilities.setWarningLabel(warning, INDEX_MODIFIED); 134 135 gbc.gridy ++; 136 JPanel buttonPanel = new JPanel(new GridBagLayout()); 137 buttonPanel.setOpaque(false); 138 gbc.insets = new Insets(10, 10, 10, 10); 139 add(buttonPanel, gbc); 140 141 gbc.insets = new Insets(0, 0, 0, 0); 142 gbc.gridy = 0; 143 gbc.gridx = 0; 144 gbc.weightx = 0.0; 145 gbc.gridwidth = 1; 146 deleteIndex.setOpaque(false); 147 gbc.insets.left = 0; 148 buttonPanel.add(deleteIndex, gbc); 149 deleteIndex.addActionListener(new ActionListener() 150 { 151 @Override 152 public void actionPerformed(ActionEvent ev) 153 { 154 deleteIndex(); 155 } 156 }); 157 gbc.gridx = 2; 158 gbc.weightx = 1.0; 159 buttonPanel.add(Box.createHorizontalGlue(), gbc); 160 gbc.weightx = 0.0; 161 gbc.insets.left = 10; 162 saveChanges.setOpaque(false); 163 gbc.gridx = 3; 164 buttonPanel.add(saveChanges, gbc); 165 saveChanges.addActionListener(new ActionListener() 166 { 167 @Override 168 public void actionPerformed(ActionEvent ev) 169 { 170 saveIndex(false); 171 } 172 }); 173 174 entryLimit.getDocument().addDocumentListener(new DocumentListener() 175 { 176 @Override 177 public void insertUpdate(DocumentEvent ev) 178 { 179 checkSaveButton(); 180 } 181 182 @Override 183 public void changedUpdate(DocumentEvent ev) 184 { 185 checkSaveButton(); 186 } 187 188 @Override 189 public void removeUpdate(DocumentEvent ev) 190 { 191 checkSaveButton(); 192 } 193 }); 194 195 ActionListener listener = new ActionListener() 196 { 197 @Override 198 public void actionPerformed(ActionEvent ev) 199 { 200 checkSaveButton(); 201 } 202 }; 203 for (JCheckBox cb : types) 204 { 205 cb.addActionListener(listener); 206 } 207 } 208 209 @Override 210 public LocalizableMessage getTitle() 211 { 212 return INFO_CTRL_PANEL_INDEX_PANEL_TITLE.get(); 213 } 214 215 @Override 216 public Component getPreferredFocusComponent() 217 { 218 return entryLimit; 219 } 220 221 @Override 222 public void configurationChanged(ConfigurationChangeEvent ev) 223 { 224 final ServerDescriptor desc = ev.getNewDescriptor(); 225 updateErrorPaneIfAuthRequired(desc, 226 isLocal() ? 227 INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_INDEX_EDITING.get() : 228 INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname())); 229 SwingUtilities.invokeLater(new Runnable() 230 { 231 @Override 232 public void run() 233 { 234 checkSaveButton(); 235 deleteIndex.setEnabled(!authenticationRequired(desc)); 236 } 237 }); 238 } 239 240 @Override 241 public void okClicked() 242 { 243 } 244 245 /** 246 * Method used to know if there are unsaved changes or not. It is used by the 247 * index selection listener when the user changes the selection. 248 * 249 * @return <CODE>true</CODE> if there are unsaved changes (and so the 250 * selection of the index should be canceled) and <CODE>false</CODE> 251 * otherwise. 252 */ 253 public boolean mustCheckUnsavedChanges() 254 { 255 return index != null && 256 saveChanges.isVisible() && saveChanges.isEnabled(); 257 } 258 259 /** 260 * Tells whether the user chose to save the changes in the panel, to not save 261 * them or simply cancelled the selection in the tree. 262 * 263 * @return the value telling whether the user chose to save the changes in the 264 * panel, to not save them or simply cancelled the selection change in 265 * the tree. 266 */ 267 public UnsavedChangesDialog.Result checkUnsavedChanges() 268 { 269 UnsavedChangesDialog.Result result; 270 UnsavedChangesDialog unsavedChangesDlg = new UnsavedChangesDialog(Utilities.getParentDialog(this), getInfo()); 271 unsavedChangesDlg.setMessage(INFO_CTRL_PANEL_UNSAVED_CHANGES_SUMMARY.get(), 272 INFO_CTRL_PANEL_UNSAVED_INDEX_CHANGES_DETAILS.get(index.getName())); 273 Utilities.centerGoldenMean(unsavedChangesDlg, Utilities.getParentDialog(this)); 274 unsavedChangesDlg.setVisible(true); 275 result = unsavedChangesDlg.getResult(); 276 if (result == UnsavedChangesDialog.Result.SAVE) 277 { 278 saveIndex(false); 279 if (newModifyTask == null || // The user data is not valid 280 newModifyTask.getState() != Task.State.FINISHED_SUCCESSFULLY) 281 { 282 result = UnsavedChangesDialog.Result.CANCEL; 283 } 284 } 285 286 return result; 287 } 288 289 /** Checks the enabling state of the save button. */ 290 private void checkSaveButton() 291 { 292 if (!ignoreCheckSave && index != null) 293 { 294 saveChanges.setEnabled( 295 !authenticationRequired(getInfo().getServerDescriptor()) && 296 isModified()); 297 } 298 } 299 300 private void deleteIndex() 301 { 302 List<LocalizableMessage> errors = new ArrayList<>(); 303 ProgressDialog dlg = new ProgressDialog( 304 Utilities.createFrame(), 305 Utilities.getParentDialog(this), 306 INFO_CTRL_PANEL_DELETE_INDEX_TITLE.get(), getInfo()); 307 ArrayList<AbstractIndexDescriptor> indexesToDelete = new ArrayList<>(); 308 indexesToDelete.add(index); 309 DeleteIndexTask newTask = new DeleteIndexTask(getInfo(), dlg, indexesToDelete); 310 for (Task task : getInfo().getTasks()) 311 { 312 task.canLaunch(newTask, errors); 313 } 314 315 if (errors.isEmpty()) 316 { 317 String indexName = index.getName(); 318 String backendName = index.getBackend().getBackendID(); 319 if (displayConfirmationDialog(INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 320 INFO_CTRL_PANEL_CONFIRMATION_INDEX_DELETE_DETAILS.get(indexName, backendName))) 321 { 322 launchOperation(newTask, 323 INFO_CTRL_PANEL_DELETING_INDEX_SUMMARY.get(), 324 INFO_CTRL_PANEL_DELETING_INDEX_COMPLETE.get(), 325 INFO_CTRL_PANEL_DELETING_INDEX_SUCCESSFUL.get(indexName, backendName), 326 ERR_CTRL_PANEL_DELETING_INDEX_ERROR_SUMMARY.get(), 327 ERR_CTRL_PANEL_DELETING_INDEX_ERROR_DETAILS.get(indexName), null, dlg); 328 dlg.setVisible(true); 329 } 330 } 331 else 332 { 333 displayErrorDialog(errors); 334 } 335 } 336 337 /** 338 * Saves the index modifications. 339 * 340 * @param modal 341 * whether the progress dialog for the task must be modal or not. 342 */ 343 private void saveIndex(boolean modal) 344 { 345 newModifyTask = null; 346 if (!isModified()) 347 { 348 return; 349 } 350 351 List<LocalizableMessage> errors = getErrors(); 352 353 if (errors.isEmpty()) 354 { 355 ProgressDialog dlg = new ProgressDialog( 356 Utilities.getFrame(this), 357 Utilities.getFrame(this), 358 INFO_CTRL_PANEL_MODIFYING_INDEX_TITLE.get(), getInfo()); 359 dlg.setModal(modal); 360 newModifyTask = new ModifyIndexTask(getInfo(), dlg); 361 for (Task task : getInfo().getTasks()) 362 { 363 task.canLaunch(newModifyTask, errors); 364 } 365 if (errors.isEmpty()) 366 { 367 String attributeName = index.getName(); 368 String backendName = index.getBackend().getBackendID(); 369 launchOperation(newModifyTask, 370 INFO_CTRL_PANEL_MODIFYING_INDEX_SUMMARY.get(attributeName), 371 INFO_CTRL_PANEL_MODIFYING_INDEX_COMPLETE.get(), 372 INFO_CTRL_PANEL_MODIFYING_INDEX_SUCCESSFUL.get(attributeName, backendName), 373 ERR_CTRL_PANEL_MODIFYING_INDEX_ERROR_SUMMARY.get(), 374 ERR_CTRL_PANEL_MODIFYING_INDEX_ERROR_DETAILS.get(attributeName), null, dlg); 375 saveChanges.setEnabled(false); 376 dlg.setVisible(true); 377 } 378 } 379 380 if (!errors.isEmpty()) 381 { 382 displayErrorDialog(errors); 383 } 384 } 385 386 /** 387 * Updates the contents of the panel with the provided index. 388 * 389 * @param index 390 * the index descriptor to be used to update the panel. 391 */ 392 public void update(IndexDescriptor index) 393 { 394 ignoreCheckSave = true; 395 setPrimaryValid(lEntryLimit); 396 setPrimaryValid(lType); 397 name.setText(index.getName()); 398 backendName.setText(index.getBackend().getBackendID()); 399 titlePanel.setDetails(LocalizableMessage.raw(index.getName())); 400 entryLimit.setText(String.valueOf(index.getEntryLimit())); 401 approximate.setSelected(false); 402 equality.setSelected(false); 403 ordering.setSelected(false); 404 substring.setSelected(false); 405 presence.setSelected(false); 406 for (IndexTypeDescriptor type : index.getTypes()) 407 { 408 switch(type) 409 { 410 case APPROXIMATE: 411 approximate.setSelected(true); 412 break; 413 case PRESENCE: 414 presence.setSelected(true); 415 break; 416 case EQUALITY: 417 equality.setSelected(true); 418 break; 419 case ORDERING: 420 ordering.setSelected(true); 421 break; 422 case SUBSTRING: 423 substring.setSelected(true); 424 break; 425 } 426 } 427 428 JComponent[] comps = {entryLimit, lType, typesPanel, lEntryLimit}; 429 430 for (JComponent comp : comps) 431 { 432 comp.setVisible(!index.isDatabaseIndex()); 433 } 434 435 AttributeType attr = index.getAttributeType(); 436 repopulateTypesPanel(attr); 437 438 if (index.isDatabaseIndex()) 439 { 440 entryLimit.setText(""); 441 } 442 saveChanges.setVisible(!index.isDatabaseIndex()); 443 deleteIndex.setVisible(!index.isDatabaseIndex()); 444 if (index.isDatabaseIndex()) 445 { 446 Utilities.setWarningLabel(warning, NON_CONFIGURABLE_INDEX); 447 warning.setVisible(true); 448 } 449 else if (getInfo() != null) 450 { 451 if (getInfo().mustReindex(index)) 452 { 453 Utilities.setWarningLabel(warning, INDEX_MODIFIED); 454 warning.setVisible(true); 455 warning.setVerticalTextPosition(SwingConstants.TOP); 456 } 457 else 458 { 459 warning.setVisible(false); 460 } 461 } 462 this.index = index; 463 464 ignoreCheckSave = false; 465 checkSaveButton(); 466 467 scrollListener.updateBorder(); 468 } 469 470 /** 471 * Returns <CODE>true</CODE> if the index has been modified and 472 * <CODE>false</CODE> otherwise. 473 * 474 * @return <CODE>true</CODE> if the index has been modified and 475 * <CODE>false</CODE> otherwise. 476 */ 477 private boolean isModified() 478 { 479 return !getTypes().equals(index.getTypes()) || 480 !String.valueOf(index.getEntryLimit()).equals(entryLimit.getText()); 481 } 482 483 /** 484 * The task in charge of modifying the index. 485 */ 486 protected class ModifyIndexTask extends Task 487 { 488 private Set<String> backendSet; 489 private String attributeName; 490 private String backendName; 491 private int entryLimitValue; 492 private IndexDescriptor indexToModify; 493 private SortedSet<IndexTypeDescriptor> indexTypes = new TreeSet<>(); 494 private IndexDescriptor modifiedIndex; 495 496 /** 497 * The constructor of the task. 498 * 499 * @param info 500 * the control panel info. 501 * @param dlg 502 * the progress dialog that shows the progress of the task. 503 */ 504 public ModifyIndexTask(ControlPanelInfo info, ProgressDialog dlg) 505 { 506 super(info, dlg); 507 backendName = index.getBackend().getBackendID(); 508 backendSet = new HashSet<>(); 509 backendSet.add(backendName); 510 attributeName = index.getName(); 511 entryLimitValue = Integer.parseInt(entryLimit.getText()); 512 indexTypes = getTypes(); 513 514 indexToModify = index; 515 } 516 517 @Override 518 public Type getType() 519 { 520 return Type.MODIFY_INDEX; 521 } 522 523 @Override 524 public Set<String> getBackends() 525 { 526 return backendSet; 527 } 528 529 @Override 530 public LocalizableMessage getTaskDescription() 531 { 532 return INFO_CTRL_PANEL_MODIFY_INDEX_TASK_DESCRIPTION.get(attributeName, 533 backendName); 534 } 535 536 @Override 537 public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons) 538 { 539 boolean canLaunch = true; 540 if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) 541 { 542 // All the operations are incompatible if they apply to this 543 // backend for safety. This is a short operation so the limitation 544 // has not a lot of impact. 545 Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends()); 546 backends.retainAll(getBackends()); 547 if (!backends.isEmpty()) 548 { 549 incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); 550 canLaunch = false; 551 } 552 } 553 return canLaunch; 554 } 555 556 /** 557 * Updates the configuration of the modified index. 558 * 559 * @throws OpenDsException 560 * if there is an error updating the configuration. 561 */ 562 private void updateConfiguration() throws OpenDsException 563 { 564 boolean configHandlerUpdated = false; 565 try 566 { 567 if (!isServerRunning()) 568 { 569 configHandlerUpdated = true; 570 getInfo().stopPooling(); 571 if (getInfo().mustDeregisterConfig()) 572 { 573 DirectoryServer.deregisterBaseDN(DN.valueOf("cn=config")); 574 } 575 DirectoryServer.getInstance().initializeConfiguration( 576 org.opends.server.extensions.ConfigFileHandler.class.getName(), ConfigReader.configFile); 577 getInfo().setMustDeregisterConfig(true); 578 } 579 else 580 { 581 SwingUtilities.invokeLater(new Runnable() 582 { 583 @Override 584 public void run() 585 { 586 StringBuilder sb = new StringBuilder(); 587 sb.append(getConfigCommandLineName()); 588 List<String> args = getObfuscatedCommandLineArguments(getDSConfigCommandLineArguments()); 589 args.removeAll(getConfigCommandLineArguments()); 590 591 printEquivalentCommandLine( 592 getConfigCommandLineName(), args, INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_MODIFY_INDEX.get()); 593 } 594 }); 595 } 596 597 SwingUtilities.invokeLater(new Runnable() 598 { 599 @Override 600 public void run() 601 { 602 getProgressDialog().appendProgressHtml( 603 Utilities.getProgressWithPoints( 604 INFO_CTRL_PANEL_MODIFYING_INDEX_PROGRESS.get(attributeName), 605 ColorAndFontConstants.progressFont)); 606 } 607 }); 608 609 if (isServerRunning()) 610 { 611 modifyIndexOnline(getInfo().getDirContext()); 612 } 613 else 614 { 615 modifyIndexOffline(backendName, attributeName, indexToModify, indexTypes, entryLimitValue); 616 } 617 618 SwingUtilities.invokeLater(new Runnable() 619 { 620 @Override 621 public void run() 622 { 623 getProgressDialog().appendProgressHtml( 624 Utilities.getProgressDone(ColorAndFontConstants.progressFont)); 625 } 626 }); 627 } 628 finally 629 { 630 if (configHandlerUpdated) 631 { 632 DirectoryServer.getInstance().initializeConfiguration(ConfigReader.configClassName, ConfigReader.configFile); 633 getInfo().startPooling(); 634 } 635 } 636 } 637 638 /** 639 * Modifies index using the provided connection. 640 * 641 * @param ctx 642 * the connection to be used to update the index configuration. 643 * @throws OpenDsException 644 * if there is an error updating the server. 645 */ 646 private void modifyIndexOnline(final InitialLdapContext ctx) throws OpenDsException 647 { 648 final ManagementContext mCtx = LDAPManagementContext.createFromContext(JNDIDirContextAdaptor.adapt(ctx)); 649 final BackendCfgClient backend = mCtx.getRootConfiguration().getBackend(backendName); 650 modifyBackendIndexOnline((PluggableBackendCfgClient) backend); 651 } 652 653 private void modifyBackendIndexOnline(final PluggableBackendCfgClient backend) throws OpenDsException 654 { 655 final BackendIndexCfgClient index = backend.getBackendIndex(attributeName); 656 if (!indexTypes.equals(indexToModify.getTypes())) 657 { 658 index.setIndexType(IndexTypeDescriptor.toBackendIndexTypes(indexTypes)); 659 } 660 661 if (entryLimitValue != index.getIndexEntryLimit()) 662 { 663 index.setIndexEntryLimit(entryLimitValue); 664 } 665 index.commit(); 666 } 667 668 @Override 669 protected String getCommandLinePath() 670 { 671 return null; 672 } 673 674 @Override 675 protected ArrayList<String> getCommandLineArguments() 676 { 677 return new ArrayList<>(); 678 } 679 680 /** 681 * Returns the full command-line path of the dsconfig command-line if we can 682 * provide an equivalent command-line (the server is running). 683 * 684 * @return the full command-line path of the dsconfig command-line if we can 685 * provide an equivalent command-line (the server is running). 686 */ 687 private String getConfigCommandLineName() 688 { 689 if (isServerRunning() && isModified()) 690 { 691 return getCommandLinePath("dsconfig"); 692 } 693 else 694 { 695 return null; 696 } 697 } 698 699 @Override 700 public void runTask() 701 { 702 state = State.RUNNING; 703 lastException = null; 704 705 try 706 { 707 updateConfiguration(); 708 modifiedIndex = new IndexDescriptor(attributeName, 709 indexToModify.getAttributeType(), 710 indexToModify.getBackend(), 711 indexTypes, 712 entryLimitValue); 713 getInfo().registerModifiedIndex(modifiedIndex); 714 state = State.FINISHED_SUCCESSFULLY; 715 } 716 catch (Throwable t) 717 { 718 lastException = t; 719 state = State.FINISHED_WITH_ERROR; 720 } 721 } 722 723 @Override 724 public void postOperation() 725 { 726 if (lastException == null && state == State.FINISHED_SUCCESSFULLY) 727 { 728 rebuildIndexIfNecessary(modifiedIndex, getProgressDialog()); 729 } 730 } 731 732 private List<String> getDSConfigCommandLineArguments() 733 { 734 List<String> args = new ArrayList<>(); 735 args.add("set-backend-index-prop"); 736 args.add("--backend-name"); 737 args.add(backendName); 738 739 args.add("--index-name"); 740 args.add(attributeName); 741 742 if (!indexTypes.equals(indexToModify.getTypes())) 743 { 744 // To add 745 Set<IndexTypeDescriptor> toAdd = new TreeSet<>(); 746 for (IndexTypeDescriptor newType : indexTypes) 747 { 748 if (!indexToModify.getTypes().contains(newType)) 749 { 750 toAdd.add(newType); 751 } 752 } 753 // To delete 754 Set<IndexTypeDescriptor> toDelete = new TreeSet<>(); 755 for (IndexTypeDescriptor oldType : indexToModify.getTypes()) 756 { 757 if (!indexTypes.contains(oldType)) 758 { 759 toDelete.add(oldType); 760 } 761 } 762 for (IndexTypeDescriptor newType : toDelete) 763 { 764 args.add("--remove"); 765 args.add("index-type:" + newType); 766 } 767 for (IndexTypeDescriptor newType : toAdd) 768 { 769 args.add("--add"); 770 args.add("index-type:" + newType.toBackendIndexType()); 771 } 772 } 773 if (entryLimitValue != indexToModify.getEntryLimit()) 774 { 775 args.add("--set"); 776 args.add("index-entry-limit:"+entryLimitValue); 777 } 778 args.addAll(getConnectionCommandLineArguments()); 779 args.add("--no-prompt"); 780 return args; 781 } 782 } 783}