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