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