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-2010 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.*;
031import static org.opends.server.util.CollectionUtils.*;
032
033import java.awt.Component;
034import java.awt.GridBagConstraints;
035import java.awt.GridBagLayout;
036import java.io.File;
037import java.util.ArrayList;
038import java.util.Collection;
039import java.util.Collections;
040import java.util.Comparator;
041import java.util.HashMap;
042import java.util.HashSet;
043import java.util.LinkedHashSet;
044import java.util.List;
045import java.util.Map;
046import java.util.Set;
047
048import javax.swing.DefaultComboBoxModel;
049import javax.swing.JCheckBox;
050import javax.swing.JComboBox;
051import javax.swing.JLabel;
052import javax.swing.JList;
053import javax.swing.JPanel;
054import javax.swing.JTextField;
055import javax.swing.ListCellRenderer;
056import javax.swing.SwingUtilities;
057import javax.swing.event.ChangeEvent;
058import javax.swing.event.ChangeListener;
059
060import org.forgerock.i18n.LocalizableMessage;
061import org.forgerock.i18n.LocalizableMessageBuilder;
062import org.forgerock.opendj.ldap.schema.ObjectClassType;
063import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
064import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
065import org.opends.guitools.controlpanel.event.ConfigurationElementCreatedListener;
066import org.opends.guitools.controlpanel.event.SuperiorObjectClassesChangedEvent;
067import org.opends.guitools.controlpanel.event.SuperiorObjectClassesChangedListener;
068import org.opends.guitools.controlpanel.task.NewSchemaElementsTask;
069import org.opends.guitools.controlpanel.task.Task;
070import org.opends.guitools.controlpanel.ui.components.BasicExpander;
071import org.opends.guitools.controlpanel.ui.components.DoubleAddRemovePanel;
072import org.opends.guitools.controlpanel.ui.components.SuperiorObjectClassesEditor;
073import org.opends.guitools.controlpanel.ui.renderer.SchemaElementComboBoxCellRenderer;
074import org.opends.guitools.controlpanel.util.Utilities;
075import org.opends.server.config.ConfigConstants;
076import org.opends.server.types.AttributeType;
077import org.opends.server.types.ObjectClass;
078import org.opends.server.types.Schema;
079import org.opends.server.util.ServerConstants;
080import org.opends.server.util.StaticUtils;
081
082/** The panel displayed when the user wants to define a new object class in the schema. */
083public class NewObjectClassPanel extends StatusGenericPanel
084{
085 private static final long serialVersionUID = -4956885827963184571L;
086  private JLabel lName = Utilities.createPrimaryLabel(
087      INFO_CTRL_PANEL_OBJECTCLASS_NAME_LABEL.get());
088  private JLabel lSuperior = Utilities.createPrimaryLabel(
089      INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get());
090  private JLabel lOID = Utilities.createPrimaryLabel(
091      INFO_CTRL_PANEL_OBJECTCLASS_OID_LABEL.get());
092  private JLabel lAliases = Utilities.createPrimaryLabel(
093      INFO_CTRL_PANEL_OBJECTCLASS_ALIASES_LABEL.get());
094  private JLabel lOrigin = Utilities.createPrimaryLabel(
095      INFO_CTRL_PANEL_OBJECTCLASS_ORIGIN_LABEL.get());
096  private JLabel lFile = Utilities.createPrimaryLabel(
097      INFO_CTRL_PANEL_OBJECTCLASS_FILE_LABEL.get());
098  private JTextField aliases = Utilities.createLongTextField();
099  private JLabel lDescription = Utilities.createPrimaryLabel(
100      INFO_CTRL_PANEL_OBJECTCLASS_DESCRIPTION_LABEL.get());
101  private JLabel lType = Utilities.createPrimaryLabel(
102      INFO_CTRL_PANEL_OBJECTCLASS_TYPE_LABEL.get());
103  private JLabel lAttributes = Utilities.createPrimaryLabel(
104      INFO_CTRL_PANEL_OBJECTCLASS_ATTRIBUTES_LABEL.get());
105
106  private Set<AttributeType> inheritedOptionalAttributes = new HashSet<>();
107  private Set<AttributeType> inheritedRequiredAttributes = new HashSet<>();
108
109  private JLabel[] labels = {lName, lSuperior, lOID, lAliases, lOrigin, lFile,
110      lDescription, lType, lAttributes
111  };
112
113  private JTextField name = Utilities.createMediumTextField();
114  private SuperiorObjectClassesEditor superiors = new
115  SuperiorObjectClassesEditor();
116  private JComboBox type = Utilities.createComboBox();
117  private JTextField oid = Utilities.createMediumTextField();
118  private JTextField description = Utilities.createLongTextField();
119  private JTextField origin = Utilities.createLongTextField();
120  private JTextField file = Utilities.createLongTextField();
121  private JCheckBox obsolete = Utilities.createCheckBox(
122      INFO_CTRL_PANEL_OBJECTCLASS_OBSOLETE_LABEL.get());
123  private DoubleAddRemovePanel<AttributeType> attributes;
124
125  private Schema schema;
126
127  private Component relativeComponent;
128
129  /**
130   * Constructor of the new object class panel.
131   * @param relativeComponent the component relative to which the dialog
132   * containing this panel must be centered.
133   */
134  public NewObjectClassPanel(Component relativeComponent)
135  {
136    super();
137    this.relativeComponent = relativeComponent;
138    createLayout();
139  }
140
141  /** {@inheritDoc} */
142  public LocalizableMessage getTitle()
143  {
144    return INFO_CTRL_PANEL_NEW_OBJECTCLASS_PANEL_TITLE.get();
145  }
146
147  /** {@inheritDoc} */
148  public Component getPreferredFocusComponent()
149  {
150    return name;
151  }
152
153  /** {@inheritDoc} */
154  public void configurationChanged(ConfigurationChangeEvent ev)
155  {
156    final ServerDescriptor desc = ev.getNewDescriptor();
157    Schema s = desc.getSchema();
158
159    final boolean[] repack = {schema == null};
160    final boolean[] error = {false};
161
162    final boolean schemaChanged;
163    if (schema != null && s != null)
164    {
165      schemaChanged = !ServerDescriptor.areSchemasEqual(s, schema);
166    }
167    else if (schema == null && s != null)
168    {
169      schemaChanged = true;
170    }
171    else if (s == null && schema != null)
172    {
173      schemaChanged = false;
174    }
175    else
176    {
177      schemaChanged = false;
178    }
179    if (schemaChanged)
180    {
181      schema = s;
182    }
183    else if (schema == null)
184    {
185      updateErrorPane(errorPane,
186          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
187          ColorAndFontConstants.errorTitleFont,
188          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get(),
189          ColorAndFontConstants.defaultFont);
190      repack[0] = true;
191      error[0] = true;
192    }
193    SwingUtilities.invokeLater(new Runnable()
194    {
195      public void run()
196      {
197        setEnabledOK(!error[0]);
198        errorPane.setVisible(error[0]);
199        if (schema != null && schemaChanged)
200        {
201          superiors.setSchema(schema);
202          updateAttributes();
203        }
204        if (repack[0])
205        {
206          packParentDialog();
207          if (relativeComponent != null)
208          {
209            Utilities.centerGoldenMean(
210                Utilities.getParentDialog(NewObjectClassPanel.this),
211                relativeComponent);
212          }
213        }
214      }
215    });
216    if (!error[0])
217    {
218      updateErrorPaneAndOKButtonIfAuthRequired(desc,
219          isLocal() ?
220   INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_TO_CREATE_OBJECTCLASS_SUMMARY.get() :
221     INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname()));
222    }
223  }
224
225  /** {@inheritDoc} */
226  public void okClicked()
227  {
228    ArrayList<LocalizableMessage> errors = new ArrayList<>();
229    for (JLabel label : labels)
230    {
231      setPrimaryValid(label);
232    }
233    String n = getObjectClassName();
234    LocalizableMessageBuilder err = new LocalizableMessageBuilder();
235    if (n.length() == 0)
236    {
237      errors.add(ERR_CTRL_PANEL_OBJECTCLASS_NAME_REQUIRED.get());
238    }
239    else if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
240    {
241      errors.add(ERR_CTRL_PANEL_INVALID_OBJECTCLASS_NAME.get(err));
242      err = new LocalizableMessageBuilder();
243    }
244    else
245    {
246      LocalizableMessage elementType = NewAttributePanel.getSchemaElementType(n, schema);
247      if (elementType != null)
248      {
249        errors.add(ERR_CTRL_PANEL_OBJECTCLASS_NAME_ALREADY_IN_USE.get(n, elementType));
250      }
251    }
252
253    n = oid.getText().trim();
254    if (n.length() > 0)
255    {
256      if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
257      {
258        errors.add(ERR_CTRL_PANEL_OID_NOT_VALID.get(err));
259        err = new LocalizableMessageBuilder();
260      }
261      else
262      {
263        LocalizableMessage elementType = NewAttributePanel.getSchemaElementType(n, schema);
264        if (elementType != null)
265        {
266          errors.add(ERR_CTRL_PANEL_OID_ALREADY_IN_USE.get(n, elementType));
267        }
268      }
269    }
270
271    if (aliases.getText().trim().length() > 0)
272    {
273      String[] al = aliases.getText().split(",");
274      if (al.length > 0)
275      {
276        for (String alias : al)
277        {
278          if (alias.trim().length() == 0)
279          {
280            errors.add(ERR_CTRL_PANEL_EMPTY_ALIAS.get());
281          }
282          else
283          {
284            LocalizableMessage elementType = NewAttributePanel.getSchemaElementType(
285                alias, schema);
286            if (elementType != null)
287            {
288              errors.add(ERR_CTRL_PANEL_ALIAS_ALREADY_IN_USE.get(n, elementType));
289            }
290          }
291        }
292      }
293    }
294
295    checkCompatibleSuperiors(getObjectClassSuperiors(), getObjectClassType(),
296        errors);
297
298    ProgressDialog dlg = new ProgressDialog(
299        Utilities.createFrame(),
300        Utilities.getParentDialog(this),
301        INFO_CTRL_PANEL_NEW_OBJECTCLASS_PANEL_TITLE.get(), getInfo());
302    NewSchemaElementsTask newTask = null;
303    if (errors.isEmpty())
304    {
305      LinkedHashSet<AttributeType> attributes = new LinkedHashSet<>(0);
306      LinkedHashSet<ObjectClass> ocs = new LinkedHashSet<>(1);
307      ocs.add(getObjectClass());
308      newTask = new NewSchemaElementsTask(getInfo(), dlg, ocs, attributes);
309      for (Task task : getInfo().getTasks())
310      {
311        task.canLaunch(newTask, errors);
312      }
313      for (ConfigurationElementCreatedListener listener :
314        getConfigurationElementCreatedListeners())
315      {
316        newTask.addConfigurationElementCreatedListener(listener);
317      }
318    }
319    if (errors.isEmpty())
320    {
321      String ocName = getObjectClassName();
322      launchOperation(newTask,
323          INFO_CTRL_PANEL_CREATING_OBJECTCLASS_SUMMARY.get(ocName),
324          INFO_CTRL_PANEL_CREATING_OBJECTCLASS_COMPLETE.get(),
325          INFO_CTRL_PANEL_CREATING_OBJECTCLASS_SUCCESSFUL.get(ocName),
326          ERR_CTRL_PANEL_CREATING_OBJECTCLASS_ERROR_SUMMARY.get(),
327          ERR_CTRL_PANEL_CREATING_OBJECTCLASS_ERROR_DETAILS.get(ocName),
328          null,
329          dlg);
330      dlg.setVisible(true);
331      name.setText("");
332      oid.setText("");
333      description.setText("");
334      aliases.setText("");
335      superiors.setSelectedSuperiors(
336          Collections.singleton(schema.getObjectClass("top")));
337      attributes.getAvailableListModel().addAll(
338          attributes.getSelectedListModel1().getData());
339      attributes.getAvailableListModel().addAll(
340          attributes.getSelectedListModel2().getData());
341      attributes.getSelectedListModel1().clear();
342      attributes.getSelectedListModel2().clear();
343      name.grabFocus();
344      Utilities.getParentDialog(this).setVisible(false);
345    }
346    else
347    {
348      displayErrorDialog(errors);
349    }
350  }
351
352  private void updateAttributes()
353  {
354    int[][] selected =
355    {
356      attributes.getAvailableList().getSelectedIndices(),
357      attributes.getSelectedList1().getSelectedIndices(),
358      attributes.getSelectedList2().getSelectedIndices()
359    };
360    JList[] lists =
361    {
362        attributes.getAvailableList(),
363        attributes.getSelectedList1(),
364        attributes.getSelectedList2()
365    };
366    attributes.getAvailableListModel().clear();
367    Collection<AttributeType> allAttrs =
368      schema.getAttributeTypes().values();
369    attributes.getAvailableListModel().addAll(allAttrs);
370
371
372    HashSet<AttributeType> toDelete = new HashSet<>();
373    for (AttributeType attr : attributes.getSelectedListModel1().getData())
374    {
375      if (!allAttrs.contains(attr))
376      {
377        toDelete.add(attr);
378      }
379      else
380      {
381        attributes.getAvailableListModel().remove(attr);
382      }
383    }
384    for (AttributeType attr : toDelete)
385    {
386      attributes.getSelectedListModel1().remove(attr);
387    }
388
389    toDelete = new HashSet<>();
390    for (AttributeType attr : attributes.getSelectedListModel2().getData())
391    {
392      if (!allAttrs.contains(attr))
393      {
394        toDelete.add(attr);
395      }
396      else
397      {
398        attributes.getAvailableListModel().remove(attr);
399      }
400    }
401    for (AttributeType attr : toDelete)
402    {
403      attributes.getSelectedListModel1().remove(attr);
404    }
405
406    int i = 0;
407    for (int[] sel : selected)
408    {
409      if (sel != null)
410      {
411        ArrayList<Integer> indexes = new ArrayList<>();
412        for (int element : sel)
413        {
414          if (element < lists[i].getModel().getSize())
415          {
416            indexes.add(element);
417          }
418        }
419        int[] newSelection = new int[indexes.size()];
420        for (int j=0; j<newSelection.length; j++)
421        {
422          newSelection[j] = indexes.get(j);
423        }
424        lists[i].setSelectedIndices(newSelection);
425      }
426      i++;
427    }
428  }
429
430  /**
431   * Creates the layout of the panel (but the contents are not populated here).
432   */
433  private void createLayout()
434  {
435    GridBagConstraints gbc = new GridBagConstraints();
436
437    Utilities.setRequiredIcon(lName);
438
439    gbc.gridwidth = 2;
440    gbc.gridy = 0;
441    addErrorPane(gbc);
442
443    gbc.gridy ++;
444    gbc.gridwidth = 1;
445    gbc.weighty = 0.0;
446    gbc.gridx = 1;
447    gbc.anchor = GridBagConstraints.EAST;
448    gbc.fill = GridBagConstraints.NONE;
449    JLabel requiredLabel = createRequiredLabel();
450    gbc.insets.bottom = 10;
451    add(requiredLabel, gbc);
452
453    gbc.gridy ++;
454    gbc.fill = GridBagConstraints.HORIZONTAL;
455    gbc.anchor = GridBagConstraints.WEST;
456    gbc.insets.bottom = 0;
457
458    SuperiorObjectClassesChangedListener listener =
459      new SuperiorObjectClassesChangedListener()
460    {
461      /** {@inheritDoc} */
462      public void parentObjectClassesChanged(
463          SuperiorObjectClassesChangedEvent ev)
464      {
465        // Remove the previous inherited attributes.
466        for (AttributeType attr : inheritedRequiredAttributes)
467        {
468          attributes.getAvailableListModel().add(attr);
469          attributes.getSelectedListModel1().remove(attr);
470        }
471        for (AttributeType attr : inheritedOptionalAttributes)
472        {
473          attributes.getAvailableListModel().add(attr);
474          attributes.getSelectedListModel2().remove(attr);
475        }
476
477        inheritedOptionalAttributes.clear();
478        inheritedRequiredAttributes.clear();
479        for (ObjectClass oc : superiors.getSelectedSuperiors())
480        {
481          inheritedRequiredAttributes.addAll(oc.getRequiredAttributeChain());
482          inheritedOptionalAttributes.addAll(oc.getOptionalAttributeChain());
483        }
484        for (AttributeType attr : inheritedRequiredAttributes)
485        {
486          attributes.getAvailableListModel().remove(attr);
487          attributes.getSelectedListModel1().add(attr);
488        }
489        for (AttributeType attr : inheritedOptionalAttributes)
490        {
491          attributes.getAvailableListModel().remove(attr);
492          attributes.getSelectedListModel2().add(attr);
493        }
494        attributes.getAvailableListModel().fireContentsChanged(
495            attributes.getAvailableList(), 0,
496            attributes.getAvailableList().getModel().getSize() - 1);
497        attributes.getSelectedListModel1().fireContentsChanged(
498            attributes.getSelectedList1(), 0,
499            attributes.getSelectedList1().getModel().getSize() - 1);
500        attributes.getSelectedListModel2().fireContentsChanged(
501            attributes.getSelectedList2(), 0,
502            attributes.getSelectedList2().getModel().getSize() - 1);
503
504        Collection<AttributeType> unmovableItems = new ArrayList<>(inheritedRequiredAttributes);
505        unmovableItems.addAll(inheritedOptionalAttributes);
506        attributes.setUnmovableItems(unmovableItems);
507
508        if (ev.getNewObjectClasses().size() > 1)
509        {
510          lSuperior.setText(
511              INFO_CTRL_PANEL_OBJECTCLASS_PARENTS_LABEL.get().toString());
512        }
513        else
514        {
515          lSuperior.setText(
516              INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get().toString());
517        }
518      }
519    };
520    superiors.addParentObjectClassesChangedListener(listener);
521
522    DefaultComboBoxModel model = new DefaultComboBoxModel();
523    for (ObjectClassType t : ObjectClassType.values())
524    {
525      model.addElement(t);
526    }
527    type.setModel(model);
528    type.setSelectedItem(ObjectClassType.STRUCTURAL);
529    SchemaElementComboBoxCellRenderer renderer = new
530    SchemaElementComboBoxCellRenderer(type);
531    type.setRenderer(renderer);
532
533    attributes = new DoubleAddRemovePanel<>(0, AttributeType.class);
534    Comparator<AttributeType> comparator = new Comparator<AttributeType>()
535    {
536      /** {@inheritDoc} */
537      public int compare(AttributeType attr1, AttributeType attr2)
538      {
539        return attr1.getNameOrOID().toLowerCase().compareTo(
540            attr2.getNameOrOID().toLowerCase());
541      }
542    };
543    attributes.getAvailableListModel().setComparator(comparator);
544    attributes.getSelectedListModel1().setComparator(comparator);
545    attributes.getSelectedListModel2().setComparator(comparator);
546
547    Component[] basicComps = {name, oid, description, superiors};
548    JLabel[] basicLabels = {lName, lOID, lDescription, lSuperior};
549    JLabel[] basicInlineHelp = new JLabel[] {null, null, null, null};
550    add(basicLabels, basicComps, basicInlineHelp, this, gbc);
551
552    gbc.gridx = 0;
553    gbc.weightx = 0.0;
554    gbc.insets.left = 0;
555    gbc.fill = GridBagConstraints.HORIZONTAL;
556    gbc.anchor = GridBagConstraints.NORTHWEST;
557    add(lAttributes, gbc);
558
559    gbc.gridx ++;
560    gbc.fill = GridBagConstraints.BOTH;
561    gbc.weightx = 1.0;
562    gbc.weighty = 1.0;
563    gbc.insets.left = 10;
564    add(attributes, gbc);
565    attributes.getAvailableLabel().setText(
566        INFO_CTRL_PANEL_ADDREMOVE_AVAILABLE_ATTRIBUTES.get().toString());
567    attributes.getSelectedLabel1().setText(
568        INFO_CTRL_PANEL_ADDREMOVE_REQUIRED_ATTRIBUTES.get().toString());
569    attributes.getSelectedLabel2().setText(
570        INFO_CTRL_PANEL_ADDREMOVE_OPTIONAL_ATTRIBUTES.get().toString());
571    AttributeTypeCellRenderer listRenderer = new AttributeTypeCellRenderer();
572    attributes.getAvailableList().setCellRenderer(listRenderer);
573    attributes.getSelectedList1().setCellRenderer(listRenderer);
574    attributes.getSelectedList2().setCellRenderer(listRenderer);
575
576    gbc.gridy ++;
577    gbc.weighty = 0.0;
578    gbc.insets.top = 3;
579    JLabel explanation = Utilities.createInlineHelpLabel(
580        INFO_CTRL_PANEL_INHERITED_ATTRIBUTES_HELP.get());
581    gbc.insets.top = 3;
582    add(explanation, gbc);
583
584    final BasicExpander expander = new BasicExpander(
585        INFO_CTRL_PANEL_EXTRA_OPTIONS_EXPANDER.get());
586
587    obsolete.setText("Obsolete");
588
589    Component[] comps = {aliases, origin, file, type, obsolete};
590    JLabel[] labels = {lAliases, lOrigin, lFile, lType, null};
591    JLabel[] inlineHelps = {
592        Utilities.createInlineHelpLabel(
593            INFO_CTRL_PANEL_SEPARATED_WITH_COMMAS_HELP.get()), null,
594        Utilities.createInlineHelpLabel(
595            INFO_CTRL_PANEL_SCHEMA_FILE_OBJECTCLASS_HELP.get(File.separator)),
596            null, null};
597    gbc.gridwidth = 2;
598    gbc.gridx = 0;
599    gbc.weighty = 0.0;
600    gbc.insets.left = 0;
601    gbc.gridy ++;
602    add(expander, gbc);
603    final JPanel p = new JPanel(new GridBagLayout());
604    gbc.insets.left = 15;
605    gbc.gridy ++;
606    add(p, gbc);
607    gbc.gridy ++;
608    p.setOpaque(false);
609
610    GridBagConstraints gbc1 = new GridBagConstraints();
611    gbc1.fill = GridBagConstraints.HORIZONTAL;
612    gbc1.gridy = 0;
613
614    add(labels, comps, inlineHelps, p, gbc1);
615    ChangeListener changeListener = new ChangeListener()
616    {
617      /** {@inheritDoc} */
618      public void stateChanged(ChangeEvent e)
619      {
620        p.setVisible(expander.isSelected());
621      }
622    };
623    expander.addChangeListener(changeListener);
624    expander.setSelected(false);
625    changeListener.stateChanged(null);
626
627    file.setText(ConfigConstants.FILE_USER_SCHEMA_ELEMENTS);
628  }
629
630  private String getObjectClassName()
631  {
632    return name.getText().trim();
633  }
634
635  private String getOID()
636  {
637    String o = oid.getText().trim();
638    if (o.length() == 0)
639    {
640      o = getObjectClassName()+"-oid";
641    }
642    return o;
643  }
644
645  private Set<ObjectClass> getObjectClassSuperiors()
646  {
647    return superiors.getSelectedSuperiors();
648  }
649
650  private Map<String, List<String>> getExtraProperties()
651  {
652    Map<String, List<String>> map = new HashMap<>();
653    String f = file.getText().trim();
654    if (f.length() > 0)
655    {
656      map.put(ServerConstants.SCHEMA_PROPERTY_FILENAME, newArrayList(f));
657    }
658    String or = origin.getText().trim();
659    if (or.length() > 0)
660    {
661      map.put(ServerConstants.SCHEMA_PROPERTY_ORIGIN, newArrayList(or));
662    }
663    return map;
664  }
665
666  private ArrayList<String> getAliases()
667  {
668    ArrayList<String> al = new ArrayList<>();
669    String s = aliases.getText().trim();
670    if (s.length() > 0)
671    {
672      String[] a = s.split(",");
673      for (String alias : a)
674      {
675        al.add(alias.trim());
676      }
677    }
678    return al;
679  }
680
681  private ArrayList<String> getAllNames()
682  {
683    ArrayList<String> al = new ArrayList<>();
684    al.add(getObjectClassName());
685    al.addAll(getAliases());
686    return al;
687  }
688
689  private String getDescription()
690  {
691    return description.getText().trim();
692  }
693
694  private ObjectClass getObjectClass()
695  {
696    return new ObjectClass("", getObjectClassName(), getAllNames(),
697        getOID(),
698        getDescription(),
699        getObjectClassSuperiors(),
700        getRequiredAttributes(),
701        getOptionalAttributes(),
702        getObjectClassType(),
703        obsolete.isSelected(),
704        getExtraProperties());
705  }
706
707  private ObjectClassType getObjectClassType()
708  {
709    return (ObjectClassType)type.getSelectedItem();
710  }
711
712  private Set<AttributeType> getRequiredAttributes()
713  {
714    return intersect(attributes.getSelectedListModel1().getData(), inheritedRequiredAttributes);
715  }
716
717  private Set<AttributeType> getOptionalAttributes()
718  {
719    return intersect(attributes.getSelectedListModel2().getData(), inheritedOptionalAttributes);
720  }
721
722  private Set<AttributeType> intersect(Set<AttributeType> set1, Set<AttributeType> set2)
723  {
724    HashSet<AttributeType> attrs = new HashSet<>(set1);
725    attrs.removeAll(set2);
726    return attrs;
727  }
728
729  /**
730   * A renderer for the attribute lists.  The renderer basically marks the
731   * inherited attributes with an asterisk.
732   */
733  private class AttributeTypeCellRenderer implements ListCellRenderer
734  {
735    private ListCellRenderer defaultRenderer;
736
737    /**
738     * Renderer constructor.
739     *
740     */
741    public AttributeTypeCellRenderer()
742    {
743      defaultRenderer = attributes.getAvailableList().getCellRenderer();
744    }
745
746    /** {@inheritDoc} */
747    public Component getListCellRendererComponent(JList list, Object value,
748        int index, boolean isSelected, boolean cellHasFocus)
749    {
750      if (value instanceof AttributeType)
751      {
752        AttributeType attr = (AttributeType)value;
753        if (inheritedOptionalAttributes.contains(value) ||
754            inheritedRequiredAttributes.contains(value))
755        {
756          value = attr.getNameOrOID()+ " (*)";
757        }
758        else
759        {
760          value = attr.getNameOrOID();
761        }
762      }
763      return defaultRenderer.getListCellRendererComponent(list, value, index,
764          isSelected, cellHasFocus);
765    }
766  }
767}