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 2014-2015 ForgeRock AS
026 */
027
028package org.opends.guitools.controlpanel.ui;
029
030import static org.opends.messages.AdminToolMessages.*;
031
032import java.awt.Component;
033import java.awt.GridBagConstraints;
034import java.util.SortedSet;
035import java.util.TreeSet;
036
037import javax.swing.DefaultComboBoxModel;
038import javax.swing.JComboBox;
039import javax.swing.JLabel;
040import javax.swing.SwingUtilities;
041
042import org.opends.guitools.controlpanel.datamodel.ObjectClassValue;
043import org.opends.guitools.controlpanel.datamodel.SortableListModel;
044import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
045import org.opends.guitools.controlpanel.ui.components.AddRemovePanel;
046import org.opends.guitools.controlpanel.util.Utilities;
047import org.forgerock.i18n.LocalizableMessage;
048import org.opends.server.types.ObjectClass;
049import org.forgerock.opendj.ldap.schema.ObjectClassType;
050import org.opends.server.types.Schema;
051
052/**
053 * This is the class used to edit the object class of a given entry, it displays
054 * the structural objectclass of the entry and its auxiliary objectclasses.
055 *
056 */
057public class ObjectClassEditorPanel extends StatusGenericPanel
058{
059  private static final long serialVersionUID = 6632731109835897496L;
060  private JComboBox structural;
061  private AddRemovePanel<String> auxiliary;
062
063  private ObjectClassValue value;
064
065  private boolean valueChanged;
066
067  /**
068   * Default constructor.
069   *
070   */
071  public ObjectClassEditorPanel()
072  {
073    super();
074    createLayout();
075  }
076
077  /**
078   * Sets the object class to be displayed in the panel.
079   * @param value the object class to be displayed in the panel.
080   */
081  public void setValue(ObjectClassValue value)
082  {
083    this.value = value;
084    String struct = value.getStructural();
085    if (struct != null)
086    {
087      DefaultComboBoxModel structuralModel =
088        (DefaultComboBoxModel)structural.getModel();
089      for (int i=0; i<structuralModel.getSize(); i++)
090      {
091        if (struct.equalsIgnoreCase((String)structuralModel.getElementAt(i)))
092        {
093          structural.setSelectedIndex(i);
094          break;
095        }
096      }
097    }
098    SortableListModel<String> availableListModel =
099      auxiliary.getAvailableListModel();
100    SortableListModel<String> selectedListModel =
101      auxiliary.getSelectedListModel();
102    availableListModel.addAll(selectedListModel.getData());
103    selectedListModel.clear();
104
105    for (String oc : value.getAuxiliary())
106    {
107      int index = -1;
108      for (int i=0; i<availableListModel.getSize(); i++)
109      {
110        if (availableListModel.getElementAt(i).equalsIgnoreCase(oc))
111        {
112          index = i;
113          break;
114        }
115      }
116      if (index != -1)
117      {
118        oc = availableListModel.getElementAt(index);
119        selectedListModel.add(oc);
120        availableListModel.remove(oc);
121      }
122    }
123    selectedListModel.fireContentsChanged(
124        selectedListModel, 0, selectedListModel.getSize());
125    availableListModel.fireContentsChanged(
126        availableListModel, 0, availableListModel.getSize());
127  }
128
129  /** {@inheritDoc} */
130  public Component getPreferredFocusComponent()
131  {
132    return structural;
133  }
134
135  /** {@inheritDoc} */
136  public void cancelClicked()
137  {
138    valueChanged = false;
139    super.cancelClicked();
140  }
141
142  /**
143   * Returns the object class value displayed by the panel.
144   * @return the object class value displayed by the panel.
145   */
146  public ObjectClassValue getObjectClassValue()
147  {
148    return value;
149  }
150
151  /** {@inheritDoc} */
152  public void okClicked()
153  {
154    String struct = (String)  structural.getSelectedItem();
155    TreeSet<String> aux = new TreeSet<>(auxiliary.getSelectedListModel().getData());
156    aux.add("top");
157    ObjectClassValue newValue = new ObjectClassValue(struct, aux);
158    valueChanged = !newValue.equals(value);
159    value = newValue;
160    Utilities.getParentDialog(this).setVisible(false);
161  }
162
163  /** {@inheritDoc} */
164  public LocalizableMessage getTitle()
165  {
166    return INFO_CTRL_PANEL_EDIT_OBJECTCLASS_TITLE.get();
167  }
168
169  /** {@inheritDoc} */
170  public void configurationChanged(ConfigurationChangeEvent ev)
171  {
172    final Schema schema = ev.getNewDescriptor().getSchema();
173    if (schema != null)
174    {
175      final SortedSet<String> auxiliaryOcs = new TreeSet<>();
176      final SortedSet<String> structuralOcs = new TreeSet<>();
177      for (ObjectClass oc : schema.getObjectClasses().values())
178      {
179        if (oc.getObjectClassType() == ObjectClassType.AUXILIARY)
180        {
181          if (!oc.getNameOrOID().equals("top"))
182          {
183            auxiliaryOcs.add(oc.getNameOrOID());
184          }
185        }
186        else if (oc.getObjectClassType() == ObjectClassType.STRUCTURAL)
187        {
188          structuralOcs.add(oc.getNameOrOID());
189        }
190      }
191
192      SwingUtilities.invokeLater(new Runnable()
193      {
194        /** {@inheritDoc} */
195        public void run()
196        {
197          String currentStruct = (String)structural.getSelectedItem();
198
199          SortedSet<String> currentAux;
200          if (currentStruct != null)
201          {
202            currentAux = auxiliary.getSelectedListModel().getData();
203          }
204          else if (value != null)
205          {
206            // This is to handle the case where the schema is updated after
207            // a value was set.
208            currentStruct = value.getStructural();
209            currentAux = value.getAuxiliary();
210          }
211          else
212          {
213            currentAux = new TreeSet<>();
214          }
215          SortableListModel<String> availableListModel =
216            auxiliary.getAvailableListModel();
217          SortableListModel<String> selectedListModel =
218            auxiliary.getSelectedListModel();
219          DefaultComboBoxModel structuralModel =
220            (DefaultComboBoxModel)structural.getModel();
221          structuralModel.removeAllElements();
222          availableListModel.clear();
223          selectedListModel.clear();
224          for (String oc : structuralOcs)
225          {
226            structuralModel.addElement(oc);
227          }
228          for (String oc : auxiliaryOcs)
229          {
230            availableListModel.add(oc);
231          }
232          if (currentStruct != null)
233          {
234            structural.setSelectedItem(currentStruct);
235          }
236          for (String oc : currentAux)
237          {
238            availableListModel.remove(oc);
239            selectedListModel.add(oc);
240          }
241          selectedListModel.fireContentsChanged(
242              selectedListModel, 0, selectedListModel.getSize());
243          availableListModel.fireContentsChanged(
244              availableListModel, 0, availableListModel.getSize());
245          setEnabledOK(true);
246        }
247      });
248    }
249    else
250    {
251      updateErrorPane(errorPane,
252          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
253          ColorAndFontConstants.errorTitleFont,
254          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get(),
255          ColorAndFontConstants.defaultFont);
256      SwingUtilities.invokeLater(new Runnable()
257      {
258        /** {@inheritDoc} */
259        public void run()
260        {
261          setEnabledOK(false);
262        }
263      });
264    }
265  }
266
267  /**
268   * Returns <CODE>true</CODE> if the value changed and <CODE>false</CODE>
269   * otherwise.
270   * @return <CODE>true</CODE> if the value changed and <CODE>false</CODE>
271   * otherwise.
272   */
273  public boolean valueChanged()
274  {
275    return valueChanged;
276  }
277
278  /** {@inheritDoc} */
279  public boolean requiresScroll()
280  {
281    return false;
282  }
283
284  /**
285   * Creates the layout of the panel (but the contents are not populated here).
286   */
287  private void createLayout()
288  {
289    GridBagConstraints gbc = new GridBagConstraints();
290    gbc.gridx = 0;
291    gbc.gridy = 0;
292    gbc.weighty = 0.0;
293    gbc.weightx = 1.0;
294    gbc.fill = GridBagConstraints.BOTH;
295    gbc.gridwidth = 2;
296    addErrorPane(gbc);
297
298    gbc.gridwidth = 1;
299    gbc.fill = GridBagConstraints.HORIZONTAL;
300    gbc.weightx = 0.0;
301    JLabel l = Utilities.createPrimaryLabel(
302        INFO_CTRL_PANEL_STRUCTURAL_OBJECTCLASS_LABEL.get());
303    add(l, gbc);
304    gbc.gridx ++;
305    gbc.insets.left = 10;
306    gbc.anchor = GridBagConstraints.WEST;
307    DefaultComboBoxModel model = new DefaultComboBoxModel();
308    structural = Utilities.createComboBox();
309    structural.setModel(model);
310    gbc.weightx = 1.0;
311    add(structural, gbc);
312
313    gbc.gridy ++;
314    gbc.gridwidth = 2;
315    gbc.gridx = 0;
316    gbc.insets.top = 10;
317    gbc.insets.left = 0;
318    l = Utilities.createPrimaryLabel(
319        INFO_CTRL_PANEL_AUXILIARY_OBJECTCLASS_LABEL.get());
320    add(l, gbc);
321    gbc.gridy ++;
322    gbc.weightx = 1.0;
323    gbc.weighty = 1.0;
324    gbc.fill = GridBagConstraints.BOTH;
325    auxiliary = new AddRemovePanel<>(String.class);
326    gbc.insets.left = 30;
327    add(auxiliary, gbc);
328  }
329}