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