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