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.awt.event.ItemEvent;
026import java.awt.event.ItemListener;
027import java.io.File;
028import java.util.ArrayList;
029import java.util.Arrays;
030import java.util.Collections;
031import java.util.HashMap;
032import java.util.List;
033import java.util.Map;
034import java.util.Set;
035import java.util.SortedSet;
036import java.util.TreeSet;
037
038import javax.swing.DefaultComboBoxModel;
039import javax.swing.JCheckBox;
040import javax.swing.JComboBox;
041import javax.swing.JLabel;
042import javax.swing.JPanel;
043import javax.swing.JTextField;
044import javax.swing.SwingUtilities;
045import javax.swing.event.ChangeEvent;
046import javax.swing.event.ChangeListener;
047
048import org.forgerock.i18n.LocalizableMessage;
049import org.forgerock.i18n.LocalizableMessageBuilder;
050import org.forgerock.opendj.ldap.schema.AttributeType;
051import org.forgerock.opendj.ldap.schema.AttributeUsage;
052import org.forgerock.opendj.ldap.schema.MatchingRule;
053import org.forgerock.opendj.ldap.schema.ObjectClass;
054import org.forgerock.opendj.ldap.schema.SchemaBuilder;
055import org.forgerock.opendj.ldap.schema.Syntax;
056import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
057import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
058import org.opends.guitools.controlpanel.event.ConfigurationElementCreatedListener;
059import org.opends.guitools.controlpanel.task.NewSchemaElementsTask;
060import org.opends.guitools.controlpanel.task.Task;
061import org.opends.guitools.controlpanel.ui.components.BasicExpander;
062import org.opends.guitools.controlpanel.ui.renderer.SchemaElementComboBoxCellRenderer;
063import org.opends.guitools.controlpanel.util.LowerCaseComparator;
064import org.opends.guitools.controlpanel.util.Utilities;
065import org.opends.server.config.ConfigConstants;
066import org.opends.server.types.Schema;
067import org.opends.server.util.ServerConstants;
068import org.opends.server.util.StaticUtils;
069
070/** The panel displayed when the user wants to define a new attribute in the schema. */
071public class NewAttributePanel extends StatusGenericPanel
072{
073  private static final long serialVersionUID = 2340170241535771321L;
074
075  private static final LocalizableMessage NO_PARENT = INFO_CTRL_PANEL_NO_PARENT_FOR_ATTRIBUTE.get();
076  private static final LocalizableMessage NO_MATCHING_RULE = INFO_CTRL_PANEL_NO_MATCHING_RULE_FOR_ATTRIBUTE.get();
077
078  private final JLabel lName = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_NAME_LABEL.get());
079  private final JLabel lParent = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_PARENT_LABEL.get());
080  private final JLabel lOID = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_OID_LABEL.get());
081  private final JLabel lAliases = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_ALIASES_LABEL.get());
082  private final JLabel lOrigin = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_ORIGIN_LABEL.get());
083  private final JLabel lFile = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_FILE_LABEL.get());
084  private final JLabel lDescription = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_DESCRIPTION_LABEL.get());
085  private final JLabel lUsage = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_USAGE_LABEL.get());
086  private final JLabel lSyntax = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_ATTRIBUTE_SYNTAX_LABEL.get());
087  private final JLabel lApproximate = Utilities.createPrimaryLabel(
088      INFO_CTRL_PANEL_ATTRIBUTE_APPROXIMATE_MATCHING_RULE_LABEL.get());
089  private final JLabel lEquality = Utilities.createPrimaryLabel(
090      INFO_CTRL_PANEL_ATTRIBUTE_EQUALITY_MATCHING_RULE_LABEL.get());
091  private final JLabel lOrdering = Utilities.createPrimaryLabel(
092      INFO_CTRL_PANEL_ATTRIBUTE_ORDERING_MATCHING_RULE_LABEL.get());
093  private final JLabel lSubstring = Utilities.createPrimaryLabel(
094      INFO_CTRL_PANEL_ATTRIBUTE_SUBSTRING_MATCHING_RULE_LABEL.get());
095  private final JLabel lType = Utilities.createPrimaryLabel();
096
097  private final JLabel[] labels = { lName, lParent, lOID, lAliases, lOrigin, lFile, lDescription, lUsage, lSyntax,
098    lApproximate, lEquality, lOrdering, lSubstring, lType };
099
100  private final JTextField name = Utilities.createMediumTextField();
101  private final JComboBox<AttributeType> parent = Utilities.createComboBox();
102  private final JTextField oid = Utilities.createMediumTextField();
103  private final JTextField aliases = Utilities.createLongTextField();
104  private final JTextField description = Utilities.createLongTextField();
105  private final JTextField origin = Utilities.createLongTextField();
106  private final JTextField file = Utilities.createLongTextField();
107  private final JComboBox<AttributeUsage> usage = Utilities.createComboBox();
108  private final JComboBox<Syntax> syntax = Utilities.createComboBox();
109  private final JComboBox<MatchingRule> approximate = Utilities.createComboBox();
110  private final JComboBox<MatchingRule> equality = Utilities.createComboBox();
111  private final JComboBox<MatchingRule> ordering = Utilities.createComboBox();
112  private final JComboBox<MatchingRule> substring = Utilities.createComboBox();
113  private final JCheckBox nonModifiable = Utilities.createCheckBox(
114      INFO_CTRL_PANEL_ATTRIBUTE_NON_MODIFIABLE_LABEL.get());
115  private final JCheckBox singleValued = Utilities.createCheckBox(INFO_CTRL_PANEL_ATTRIBUTE_SINGLE_VALUED_LABEL.get());
116  private final JCheckBox collective = Utilities.createCheckBox(INFO_CTRL_PANEL_ATTRIBUTE_COLLECTIVE_LABEL.get());
117  private final JCheckBox obsolete = Utilities.createCheckBox(INFO_CTRL_PANEL_ATTRIBUTE_OBSOLETE_LABEL.get());
118
119  private Schema schema;
120
121  private final Component relativeComponent;
122
123  /**
124   * Constructor of the new attribute panel.
125   *
126   * @param relativeComponent
127   *          the component relative to which the dialog containing this panel
128   *          must be centered.
129   */
130  public NewAttributePanel(Component relativeComponent)
131  {
132    this.relativeComponent = relativeComponent;
133    createLayout();
134  }
135
136  @Override
137  public LocalizableMessage getTitle()
138  {
139    return INFO_CTRL_PANEL_NEW_ATTRIBUTE_PANEL_TITLE.get();
140  }
141
142  @Override
143  public Component getPreferredFocusComponent()
144  {
145    return name;
146  }
147
148  @Override
149  public void configurationChanged(ConfigurationChangeEvent ev)
150  {
151    List<Syntax> newSyntaxes = new ArrayList<>();
152    final ServerDescriptor desc = ev.getNewDescriptor();
153    Schema s = desc.getSchema();
154
155    final boolean firstSchema = schema == null;
156    final boolean[] repack = { firstSchema };
157    final boolean[] error = { false };
158
159    if (hasSchemaChanged(s))
160    {
161      schema = s;
162      Map<String, Syntax> syntaxNameMap = new HashMap<>();
163
164      for (Syntax syntax : schema.getSyntaxes())
165      {
166        String name = syntax.getName();
167        if (name == null)
168        {
169          name = syntax.getOID();
170        }
171        syntaxNameMap.put(name, syntax);
172      }
173
174      SortedSet<String> orderedKeys = new TreeSet<>(new LowerCaseComparator());
175      orderedKeys.addAll(syntaxNameMap.keySet());
176      for (String key : orderedKeys)
177      {
178        newSyntaxes.add(syntaxNameMap.get(key));
179      }
180      updateComboBoxModel(newSyntaxes, (DefaultComboBoxModel<Syntax>) syntax.getModel());
181
182      Map<String, AttributeType> attributeNameMap = new HashMap<>();
183      for (AttributeType attr : schema.getAttributeTypes())
184      {
185        attributeNameMap.put(attr.getNameOrOID(), attr);
186      }
187      orderedKeys.clear();
188      orderedKeys.addAll(attributeNameMap.keySet());
189      List<Object> newParents = new ArrayList<>();
190      for (String key : orderedKeys)
191      {
192        newParents.add(attributeNameMap.get(key));
193      }
194      newParents.add(0, NO_PARENT);
195      updateComboBoxModel(newParents, (DefaultComboBoxModel<AttributeType>) parent.getModel());
196
197      final List<MatchingRule> availableMatchingRules = new ArrayList<>();
198      final Map<String, MatchingRule> matchingRuleNameMap = new HashMap<>();
199      for (MatchingRule rule : schema.getMatchingRules())
200      {
201        matchingRuleNameMap.put(rule.getNameOrOID(), rule);
202      }
203
204      orderedKeys.clear();
205      orderedKeys.addAll(matchingRuleNameMap.keySet());
206      for (final String key : orderedKeys)
207      {
208        availableMatchingRules.add(matchingRuleNameMap.get(key));
209      }
210
211      final JComboBox<?>[] combos = { approximate, equality, ordering, substring };
212      for (JComboBox<?> combo : combos)
213      {
214        final DefaultComboBoxModel<?> model = (DefaultComboBoxModel<?>) combo.getModel();
215        final List<Object> el = new ArrayList<Object>(availableMatchingRules);
216        el.add(0, model.getSize() == 0 ? NO_MATCHING_RULE : model.getElementAt(0));
217        updateComboBoxModel(el, model);
218      }
219    }
220    else if (schema == null)
221    {
222      updateErrorPane(errorPane,
223          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
224          ColorAndFontConstants.errorTitleFont,
225          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get(),
226          ColorAndFontConstants.defaultFont);
227      repack[0] = true;
228      error[0] = true;
229    }
230    SwingUtilities.invokeLater(new Runnable()
231    {
232      @Override
233      public void run()
234      {
235        setEnabledOK(!error[0]);
236        errorPane.setVisible(error[0]);
237        if (firstSchema)
238        {
239          for (int i = 0; i < syntax.getModel().getSize(); i++)
240          {
241            Syntax syn = syntax.getModel().getElementAt(i);
242            if ("DirectoryString".equals(syn.getName()))
243            {
244              syntax.setSelectedIndex(i);
245              break;
246            }
247          }
248        }
249        else
250        {
251          updateDefaultMatchingRuleNames();
252        }
253
254        if (repack[0])
255        {
256          packParentDialog();
257          if (relativeComponent != null)
258          {
259            Utilities.centerGoldenMean(Utilities.getParentDialog(NewAttributePanel.this), relativeComponent);
260          }
261        }
262      }
263    });
264    if (!error[0])
265    {
266      updateErrorPaneAndOKButtonIfAuthRequired(desc,
267          isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_TO_CREATE_ATTRIBUTE_SUMMARY.get()
268                    : INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname()));
269    }
270  }
271
272  private boolean hasSchemaChanged(Schema s)
273  {
274    if (s != null)
275    {
276      return schema == null || !ServerDescriptor.areSchemasEqual(s, schema);
277    }
278    return false;
279  }
280
281  @Override
282  public void okClicked()
283  {
284    List<LocalizableMessage> errors = new ArrayList<>();
285    for (JLabel label : labels)
286    {
287      setPrimaryValid(label);
288    }
289    String n = getAttributeName();
290    LocalizableMessageBuilder err = new LocalizableMessageBuilder();
291    if (n.length() == 0)
292    {
293      errors.add(ERR_CTRL_PANEL_ATTRIBUTE_NAME_REQUIRED.get());
294      setPrimaryInvalid(lName);
295    }
296    else if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
297    {
298      errors.add(ERR_CTRL_PANEL_INVALID_ATTRIBUTE_NAME.get(err));
299      setPrimaryInvalid(lName);
300      err = new LocalizableMessageBuilder();
301    }
302    else
303    {
304      LocalizableMessage elementType = getSchemaElementType(n, schema);
305      if (elementType != null)
306      {
307        errors.add(ERR_CTRL_PANEL_ATTRIBUTE_NAME_ALREADY_IN_USE.get(n, elementType));
308        setPrimaryInvalid(lName);
309      }
310    }
311
312    n = oid.getText().trim();
313    if (n.length() > 0)
314    {
315      if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
316      {
317        errors.add(ERR_CTRL_PANEL_OID_NOT_VALID.get(err));
318        setPrimaryInvalid(lOID);
319        err = new LocalizableMessageBuilder();
320      }
321      else
322      {
323        LocalizableMessage elementType = getSchemaElementType(n, schema);
324        if (elementType != null)
325        {
326          errors.add(ERR_CTRL_PANEL_OID_ALREADY_IN_USE.get(n, elementType));
327          setPrimaryInvalid(lOID);
328        }
329      }
330    }
331
332    if (aliases.getText().trim().length() > 0)
333    {
334      String[] al = aliases.getText().split(",");
335      if (al.length > 0)
336      {
337        for (String alias : al)
338        {
339          if (alias.trim().length() == 0)
340          {
341            errors.add(ERR_CTRL_PANEL_EMPTY_ALIAS.get());
342            setPrimaryInvalid(lAliases);
343          }
344          else
345          {
346            LocalizableMessage elementType = getSchemaElementType(alias, schema);
347            if (elementType != null)
348            {
349              errors.add(ERR_CTRL_PANEL_ALIAS_ALREADY_IN_USE.get(n, elementType));
350              setPrimaryInvalid(lAliases);
351            }
352          }
353        }
354      }
355    }
356
357    setPrimaryValid(lUsage);
358    if (nonModifiable.isSelected() && AttributeUsage.USER_APPLICATIONS.equals(usage.getSelectedItem()))
359    {
360      errors.add(ERR_NON_MODIFIABLE_CANNOT_BE_USER_APPLICATIONS.get());
361      setPrimaryInvalid(lUsage);
362    }
363
364    ProgressDialog dlg = new ProgressDialog(Utilities.createFrame(), Utilities.getParentDialog(this),
365        INFO_CTRL_PANEL_NEW_ATTRIBUTE_PANEL_TITLE.get(), getInfo());
366    NewSchemaElementsTask newTask = null;
367    if (errors.isEmpty())
368    {
369      Set<ObjectClass> ocs = Collections.emptySet();
370      newTask = new NewSchemaElementsTask(getInfo(), dlg, ocs, newHashSet(getAttribute()));
371      for (Task task : getInfo().getTasks())
372      {
373        task.canLaunch(newTask, errors);
374      }
375      for (ConfigurationElementCreatedListener listener : getConfigurationElementCreatedListeners())
376      {
377        newTask.addConfigurationElementCreatedListener(listener);
378      }
379    }
380    if (errors.isEmpty())
381    {
382      String attrName = getAttributeName();
383      launchOperation(newTask,
384                      INFO_CTRL_PANEL_CREATING_ATTRIBUTE_SUMMARY.get(attrName),
385                      INFO_CTRL_PANEL_CREATING_ATTRIBUTE_COMPLETE.get(),
386                      INFO_CTRL_PANEL_CREATING_ATTRIBUTE_SUCCESSFUL.get(attrName),
387                      ERR_CTRL_PANEL_CREATING_ATTRIBUTE_ERROR_SUMMARY.get(),
388                      ERR_CTRL_PANEL_CREATING_ATTRIBUTE_ERROR_DETAILS.get(attrName),
389                      null,
390                      dlg);
391      dlg.setVisible(true);
392      name.setText("");
393      oid.setText("");
394      description.setText("");
395      aliases.setText("");
396      name.grabFocus();
397      Utilities.getParentDialog(this).setVisible(false);
398    }
399    else
400    {
401      displayErrorDialog(errors);
402    }
403  }
404
405  /**
406   * Returns the message representing the schema element type.
407   *
408   * @param name
409   *          the name of the schema element.
410   * @param schema
411   *          the schema.
412   * @return the message representing the schema element type.
413   */
414  static LocalizableMessage getSchemaElementType(String name, Schema schema)
415  {
416    if (schema.hasAttributeType(name))
417    {
418      return INFO_CTRL_PANEL_TYPE_ATTRIBUTE.get();
419    }
420    else if (schema.hasObjectClass(name))
421    {
422      return INFO_CTRL_PANEL_TYPE_OBJECT_CLASS.get();
423    }
424    else if (schema.hasSyntax(name))
425    {
426      return INFO_CTRL_PANEL_TYPE_ATTRIBUTE_SYNTAX.get();
427    }
428    else if (schema.hasMatchingRule(name))
429    {
430      return INFO_CTRL_PANEL_TYPE_MATCHING_RULE.get();
431    }
432
433    for (Syntax attr : schema.getSyntaxes())
434    {
435      if (name.equalsIgnoreCase(attr.getName()))
436      {
437        return INFO_CTRL_PANEL_TYPE_ATTRIBUTE_SYNTAX.get();
438      }
439    }
440
441    for (MatchingRule rule : schema.getMatchingRules())
442    {
443      String n = rule.getNameOrOID();
444      if (n != null && n.equalsIgnoreCase(name))
445      {
446        return INFO_CTRL_PANEL_TYPE_MATCHING_RULE.get();
447      }
448    }
449
450    return null;
451  }
452
453  /** Creates the layout of the panel (but the contents are not populated here). */
454  private void createLayout()
455  {
456    GridBagConstraints gbc = new GridBagConstraints();
457    Utilities.setRequiredIcon(lName);
458
459    gbc.gridwidth = 2;
460    gbc.gridy = 0;
461    addErrorPane(gbc);
462
463    gbc.gridy++;
464    gbc.gridwidth = 1;
465    gbc.weighty = 0.0;
466    gbc.gridx = 1;
467    gbc.anchor = GridBagConstraints.EAST;
468    gbc.fill = GridBagConstraints.NONE;
469    JLabel requiredLabel = createRequiredLabel();
470    gbc.insets.bottom = 10;
471    add(requiredLabel, gbc);
472
473    gbc.gridy++;
474    gbc.fill = GridBagConstraints.HORIZONTAL;
475    gbc.anchor = GridBagConstraints.WEST;
476    gbc.insets.bottom = 0;
477
478    JComboBox<?>[] comboBoxes = { parent, syntax, approximate, equality, ordering, substring };
479    LocalizableMessage[] defaultValues =
480        { NO_PARENT, LocalizableMessage.EMPTY, NO_MATCHING_RULE, NO_MATCHING_RULE, NO_MATCHING_RULE, NO_MATCHING_RULE };
481    SchemaElementComboBoxCellRenderer renderer = new SchemaElementComboBoxCellRenderer(syntax);
482    for (int i = 0; i < comboBoxes.length; i++)
483    {
484      DefaultComboBoxModel model = new DefaultComboBoxModel(new Object[] { defaultValues[i] });
485      comboBoxes[i].setModel(model);
486      comboBoxes[i].setRenderer(renderer);
487    }
488
489    DefaultComboBoxModel<AttributeUsage> model = new DefaultComboBoxModel<>();
490    for (AttributeUsage us : AttributeUsage.values())
491    {
492      model.addElement(us);
493    }
494    usage.setModel(model);
495    usage.setSelectedItem(AttributeUsage.USER_APPLICATIONS);
496    usage.setRenderer(renderer);
497
498    Component[] basicComps = { name, oid, description, syntax };
499    JLabel[] basicLabels = { lName, lOID, lDescription, lSyntax };
500    JLabel[] basicInlineHelp = new JLabel[] {
501      null, null, null, Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_SYNTAX_INLINE_HELP.get()) };
502    add(basicLabels, basicComps, basicInlineHelp, this, gbc);
503
504    BasicExpander[] expanders = new BasicExpander[] {
505          new BasicExpander(INFO_CTRL_PANEL_EXTRA_OPTIONS_EXPANDER.get()),
506          new BasicExpander(INFO_CTRL_PANEL_ATTRIBUTE_TYPE_OPTIONS_EXPANDER.get()),
507          new BasicExpander(INFO_CTRL_PANEL_MATCHING_RULE_OPTIONS_EXPANDER.get()) };
508
509    Component[][] comps = { { parent, aliases, origin, file },
510                            { usage, singleValued, nonModifiable, collective, obsolete },
511                            { approximate, equality, ordering, substring } };
512    JLabel[][] labels ={ { lParent, lAliases, lOrigin, lFile },
513                         { lUsage, lType, null, null, null },
514                         { lApproximate, lEquality, lOrdering, lSubstring } };
515    JLabel[][] inlineHelps = {
516          { null, Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_SEPARATED_WITH_COMMAS_HELP.get()), null,
517            Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_SCHEMA_FILE_ATTRIBUTE_HELP.get(File.separator)) },
518          { null, null, null, null, null, null },
519          { Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_MATCHING_RULE_APPROXIMATE_HELP.get()),
520            Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_MATCHING_RULE_EQUALITY_HELP.get()),
521            Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_MATCHING_RULE_ORDERING_HELP.get()),
522            Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_MATCHING_RULE_SUBSTRING_HELP.get()) } };
523    for (int i = 0; i < expanders.length; i++)
524    {
525      gbc.gridwidth = 2;
526      gbc.gridx = 0;
527      gbc.insets.left = 0;
528      add(expanders[i], gbc);
529      final JPanel p = new JPanel(new GridBagLayout());
530      gbc.insets.left = 15;
531      gbc.gridy++;
532      add(p, gbc);
533      gbc.gridy++;
534      p.setOpaque(false);
535
536      GridBagConstraints gbc1 = new GridBagConstraints();
537      gbc1.fill = GridBagConstraints.HORIZONTAL;
538      gbc1.gridy = 0;
539
540      add(labels[i], comps[i], inlineHelps[i], p, gbc1);
541      final BasicExpander expander = expanders[i];
542      ChangeListener changeListener = new ChangeListener()
543      {
544        @Override
545        public void stateChanged(ChangeEvent e)
546        {
547          p.setVisible(expander.isSelected());
548        }
549      };
550      expander.addChangeListener(changeListener);
551      expander.setSelected(false);
552      changeListener.stateChanged(null);
553    }
554    addBottomGlue(gbc);
555
556    ItemListener itemListener = new ItemListener()
557    {
558      @Override
559      public void itemStateChanged(ItemEvent ev)
560      {
561        if (ev.getStateChange() == ItemEvent.SELECTED)
562        {
563          updateDefaultMatchingRuleNames();
564          approximate.setSelectedIndex(0);
565          substring.setSelectedIndex(0);
566          equality.setSelectedIndex(0);
567          ordering.setSelectedIndex(0);
568        }
569      }
570    };
571    syntax.addItemListener(itemListener);
572
573    file.setText(ConfigConstants.FILE_USER_SCHEMA_ELEMENTS);
574  }
575
576  private void updateDefaultMatchingRuleNames()
577  {
578    Syntax syn = (Syntax) syntax.getSelectedItem();
579    if (syn != null)
580    {
581      MatchingRule[] rules = { syn.getApproximateMatchingRule(), syn.getSubstringMatchingRule(),
582        syn.getEqualityMatchingRule(), syn.getOrderingMatchingRule() };
583      JComboBox<?>[] combos = { approximate, substring, equality, ordering };
584      for (int i = 0; i < rules.length; i++)
585      {
586        DefaultComboBoxModel model = (DefaultComboBoxModel) combos[i].getModel();
587        int index = combos[i].getSelectedIndex();
588        if (model.getSize() > 0)
589        {
590          model.removeElementAt(0);
591        }
592
593        final LocalizableMessage msg =
594            rules[i] != null ? INFO_CTRL_PANEL_DEFAULT_DEFINED_IN_SYNTAX.get(rules[i].getNameOrOID())
595                             : NO_MATCHING_RULE;
596        model.insertElementAt(msg, 0);
597        combos[i].setSelectedIndex(index);
598      }
599    }
600  }
601
602  private String getAttributeName()
603  {
604    return name.getText().trim();
605  }
606
607  private String getOID()
608  {
609    String o = oid.getText().trim();
610    if (o.length() == 0)
611    {
612      o = getAttributeName() + "-oid";
613    }
614    return o;
615  }
616
617  private List<String> getAliases()
618  {
619    List<String> al = new ArrayList<>();
620    String s = aliases.getText().trim();
621    if (s.length() > 0)
622    {
623      String[] a = s.split(",");
624      for (String alias : a)
625      {
626        al.add(alias.trim());
627      }
628    }
629    return al;
630  }
631
632  private List<String> getAllNames()
633  {
634    List<String> al = new ArrayList<>();
635    al.add(getAttributeName());
636    al.addAll(getAliases());
637    return al;
638  }
639
640  private AttributeType getSuperior()
641  {
642    Object o = parent.getSelectedItem();
643    if (NO_PARENT.equals(o))
644    {
645      return null;
646    }
647    return (AttributeType) o;
648  }
649
650  private String getMatchingRuleOID(JComboBox<MatchingRule> comboBox)
651  {
652    if (comboBox.getSelectedIndex() != 0)
653    {
654      return ((MatchingRule) comboBox.getSelectedItem()).getOID();
655    }
656    return null;
657  }
658
659  private Map<String, List<String>> getExtraProperties()
660  {
661    final Map<String, List<String>> map = new HashMap<>();
662    addExtraPropertyFromTextField(file, ServerConstants.SCHEMA_PROPERTY_FILENAME, map);
663    addExtraPropertyFromTextField(origin, ServerConstants.SCHEMA_PROPERTY_ORIGIN, map);
664    return map;
665  }
666
667  private void addExtraPropertyFromTextField(
668      final JTextField value, final String key, final Map<String, List<String>> map)
669  {
670    final String trimmedValue = value.getText().trim();
671    if (!trimmedValue.trim().isEmpty())
672    {
673      map.put(key, Arrays.asList(trimmedValue));
674    }
675  }
676
677  private String getDescription()
678  {
679    return description.getText().trim();
680  }
681
682  private AttributeType getAttribute()
683  {
684    AttributeType superior = getSuperior();
685    Syntax selectedSyntax = (Syntax) syntax.getSelectedItem();
686    return new SchemaBuilder(schema.getSchemaNG()).buildAttributeType(getOID())
687      .names(getAllNames())
688      .description(getDescription())
689      .superiorType(superior != null ? superior.getNameOrOID() : null)
690      .syntax(selectedSyntax != null ? selectedSyntax.getOID() : null)
691      .approximateMatchingRule(getMatchingRuleOID(approximate))
692      .equalityMatchingRule(getMatchingRuleOID(equality))
693      .orderingMatchingRule(getMatchingRuleOID(ordering))
694      .substringMatchingRule(getMatchingRuleOID(substring))
695      .usage((AttributeUsage) usage.getSelectedItem())
696      .collective(collective.isSelected())
697      .obsolete(obsolete.isSelected())
698      .noUserModification(nonModifiable.isSelected())
699      .singleValue(singleValued.isSelected())
700      .extraProperties(getExtraProperties())
701      .addToSchema()
702      .toSchema()
703      .getAttributeType(getOID());
704  }
705}