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