/* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2010 Sun Microsystems, Inc. * Portions Copyright 2015-2016 ForgeRock AS. */ package org.opends.guitools.controlpanel.ui.components; import static org.opends.messages.AdminToolMessages.*; import java.awt.CardLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import javax.swing.Box; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import org.opends.guitools.controlpanel.event.SuperiorObjectClassesChangedEvent; import org.opends.guitools.controlpanel.event. SuperiorObjectClassesChangedListener; import org.opends.guitools.controlpanel.ui.GenericDialog; import org.opends.guitools.controlpanel.ui.SelectObjectClassesPanel; import org.opends.guitools.controlpanel.ui.renderer. SchemaElementComboBoxCellRenderer; import org.opends.guitools.controlpanel.util.LowerCaseComparator; import org.opends.guitools.controlpanel.util.Utilities; import org.opends.server.types.ObjectClass; import org.opends.server.types.Schema; /** A panel that can be used to select one (or several) object classes. */ public class SuperiorObjectClassesEditor extends JPanel { private static final long serialVersionUID = 123123973933568L; private Set toExclude = new HashSet<>(); private JComboBox singleSuperior = Utilities.createComboBox(); private JLabel multipleSuperiors = Utilities.createDefaultLabel(); private JButton bSpecifyMultiple = Utilities.createButton( INFO_CTRL_PANEL_SPECIFY_MULTIPLE_SUPERIORS_LABEL.get()); private JButton bUpdateMultiple = Utilities.createButton( INFO_CTRL_PANEL_UPDATE_MULTIPLE_SUPERIORS_LABEL.get()); private SelectObjectClassesPanel superiorsPanel; private GenericDialog superiorsDialog; private String MULTIPLE = "Multiple"; private String SINGLE = "Single"; private CardLayout cardLayout = new CardLayout(); private boolean isMultiple; private Set selectedMultipleSuperiors = new HashSet<>(); private Set listeners = new HashSet<>(); private Schema schema; /** Default constructor for this panel. */ public SuperiorObjectClassesEditor() { super(new CardLayout()); cardLayout = (CardLayout)getLayout(); setOpaque(false); createLayout(); } /** * Constructor for this panel. * @param schema a non {@code null} schema object. */ public SuperiorObjectClassesEditor(Schema schema) { this(); updateWithSchema(schema); } /** Creates the layout of this panel. */ private void createLayout() { bSpecifyMultiple.setToolTipText( INFO_CTRL_PANEL_SPECIFY_MULTIPLE_SUPERIORS_TOOLTIP.get().toString()); bSpecifyMultiple.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ev) { specifyMultipleClicked(); } }); bUpdateMultiple.setToolTipText( INFO_CTRL_PANEL_UPDATE_MULTIPLE_SUPERIORS_TOOLTIP.get().toString()); bUpdateMultiple.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ev) { updateMultipleClicked(); } }); SchemaElementComboBoxCellRenderer renderer = new SchemaElementComboBoxCellRenderer(singleSuperior); DefaultComboBoxModel model = new DefaultComboBoxModel(); singleSuperior.setModel(model); singleSuperior.setRenderer(renderer); ItemListener itemListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent ev) { notifyListeners(); } }; singleSuperior.addItemListener(itemListener); JPanel singlePanel = new JPanel(new GridBagLayout()); singlePanel.setOpaque(false); JPanel multiplePanel = new JPanel(new GridBagLayout()); multiplePanel.setOpaque(false); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.WEST; singlePanel.add(singleSuperior, gbc); multiplePanel.add(multipleSuperiors, gbc); gbc.gridx ++; gbc.insets.left = 5; gbc.weightx = 0.0; gbc.fill = GridBagConstraints.NONE; singlePanel.add(bSpecifyMultiple, gbc); multiplePanel.add(bUpdateMultiple, gbc); gbc.gridx ++; gbc.insets.left = 0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 0.1; singlePanel.add(Box.createHorizontalGlue(), gbc); multiplePanel.add(Box.createHorizontalGlue(), gbc); add(singlePanel, SINGLE); add(multiplePanel, MULTIPLE); Set empty = Collections.emptySet(); setSelectedSuperiors(empty); } /** * Sets the list of object classes that this panel should not display * (mainly used to not display the object class for which we are editing * the superior object classes). * @param toExclude the list of object classes to exclude. */ public void setObjectClassesToExclude(Set toExclude) { this.toExclude.clear(); this.toExclude.addAll(toExclude); updateWithSchema(schema); if (superiorsPanel != null) { superiorsPanel.setObjectClassesToExclude(toExclude); } } /** * Returns the list of object classes that this panel will not display. * @return the list of object classes that this panel will not display. */ public Set getObjectClassToExclude() { return Collections.unmodifiableSet(toExclude); } /** * Sets the list of superior object classes that must be displayed by * this panel. * @param objectClasses the list of superior object classes to be displayed. */ public void setSelectedSuperiors(Set objectClasses) { isMultiple = objectClasses.size() > 1; if (isMultiple) { cardLayout.show(this, MULTIPLE); selectedMultipleSuperiors.clear(); selectedMultipleSuperiors.addAll(objectClasses); updateMultipleSuperiorsLabel(selectedMultipleSuperiors); } else { if (objectClasses.size() == 1) { singleSuperior.setSelectedItem(objectClasses.iterator().next()); } cardLayout.show(this, SINGLE); } } private void updateMultipleSuperiorsLabel( Set superiors) { SortedSet orderedOcs = new TreeSet<>(new LowerCaseComparator()); for (ObjectClass oc : superiors) { orderedOcs.add(oc.getNameOrOID()); } String s = Utilities.getStringFromCollection(orderedOcs, ", "); multipleSuperiors.setText(s); } /** * Returns the list of superior object classes displayed by this panel. * @return the list of superior object classes displayed by this panel. */ public Set getSelectedSuperiors() { if (isMultiple) { return Collections.unmodifiableSet(selectedMultipleSuperiors); } ObjectClass oc = (ObjectClass)singleSuperior.getSelectedItem(); if (oc != null) { return Collections.singleton(oc); } return Collections.emptySet(); } /** * Sets the schema to be used by this panel. This method assumes that it * is being called from the event thread. * @param schema the schema to be used by this panel. */ public void setSchema(Schema schema) { updateWithSchema(schema); if (superiorsPanel != null) { superiorsPanel.setSchema(schema); } } private void updateWithSchema(Schema schema) { HashMap objectClassNameMap = new HashMap<>(); for (String key : schema.getObjectClasses().keySet()) { ObjectClass oc = schema.getObjectClass(key); if (!toExclude.contains(oc)) { objectClassNameMap.put(oc.getNameOrOID(), oc); } } SortedSet orderedKeys = new TreeSet<>(new LowerCaseComparator()); orderedKeys.addAll(objectClassNameMap.keySet()); ArrayList newParents = new ArrayList<>(); for (String key : orderedKeys) { newParents.add(objectClassNameMap.get(key)); } Utilities.updateComboBoxModel(newParents, (DefaultComboBoxModel)singleSuperior.getModel()); if (this.schema == null) { // Select the values. ObjectClass topClass = schema.getObjectClass("top"); singleSuperior.setSelectedItem(topClass); } this.schema = schema; } /** * Adds a listener that will receive events when a change is made in the * displayed superior object classes. * @param listener the listener to be added. */ public void addParentObjectClassesChangedListener( SuperiorObjectClassesChangedListener listener) { listeners.add(listener); } /** * Removes the provided listener. * @param listener the listener to be removed. */ public void removeParentObjectClassesChangedListener( SuperiorObjectClassesChangedListener listener) { listeners.remove(listener); } private void specifyMultipleClicked() { updateMultipleClicked(); } private void updateMultipleClicked() { Set selectedObjectClasses = getSelectedSuperiors(); // Display the panel with all the stuff. if (superiorsPanel == null) { superiorsPanel = new SelectObjectClassesPanel(); superiorsPanel.setSchema(schema); if (!toExclude.isEmpty()) { superiorsPanel.setObjectClassesToExclude(toExclude); } superiorsDialog = new GenericDialog(Utilities.getFrame(this), superiorsPanel); Utilities.centerGoldenMean(superiorsDialog, Utilities.getParentDialog(this)); superiorsDialog.setModal(true); superiorsDialog.pack(); } superiorsPanel.setSelectedObjectClasses(selectedObjectClasses); superiorsDialog.setVisible(true); if (!superiorsPanel.isCanceled()) { setSelectedSuperiors(superiorsPanel.getSelectedObjectClasses()); notifyListeners(); } } private void notifyListeners() { SuperiorObjectClassesChangedEvent ev = new SuperiorObjectClassesChangedEvent(this, getSelectedSuperiors()); for (SuperiorObjectClassesChangedListener listener : listeners) { listener.parentObjectClassesChanged(ev); } } }