mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

ludovicp
31.16.2010 85811b64468e9b7a876bd352a0299b904a53a3fb
Fix for Issue #615. Add support for multiple object-class inheritance.
Support added in the schema, core server and tools including Control-Panel
4 files added
42 files modified
2508 ■■■■ changed files
opends/resource/schema/00-core.ldif 10 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/browser/AbstractNodeTask.java 4 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/browser/NodeRefresher.java 2 ●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java 2 ●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedEvent.java 79 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedListener.java 45 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java 49 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java 4 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java 20 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java 77 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java 4 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java 169 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/DBEnvironmentMonitoringPanel.java 4 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/MainMenuBar.java 2 ●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java 2 ●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java 10 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java 103 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/RefreshOptionsPanel.java 14 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/SelectObjectClassesPanel.java 291 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java 9 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/StandardObjectClassPanel.java 95 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java 158 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java 2 ●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java 30 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java 4 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/components/SuperiorObjectClassesEditor.java 392 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/SchemaElementComboBoxCellRenderer.java 9 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java 93 ●●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java 10 ●●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java 2 ●●● patch | view | raw | blame | history
opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java 10 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/admin_tool.properties 29 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/ui/JavaArgumentsDialog.java 10 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/ui/RuntimeOptionsPanel.java 4 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java 20 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/ui/SelectAliasDialog.java 14 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/SchemaBackend.java 32 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java 6 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/schema/ObjectClassSyntax.java 171 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/ObjectClass.java 82 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/Schema.java 5 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/StaticUtils.java 24 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java 11 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/workflowelement/ndb/NDBAddOperation.java 18 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestObjectClass.java 373 ●●●●● patch | view | raw | blame | history
opends/resource/schema/00-core.ldif
@@ -673,13 +673,9 @@
  businessCategory $ janetMailbox $ otherMailbox $ mobileTelephoneNumber $
  pagerTelephoneNumber $ organizationalStatus $ mailPreferenceOption $
  personalSignature ) X-ORIGIN 'RFC 1274' )
objectClasses: ( 0.9.2342.19200300.100.4.20 NAME 'pilotOrganization' SUP top
  MUST ( ou $ o ) MAY ( buildingName $ businessCategory $ description $
  destinationIndicator $ facsimileTelephoneNumber $ internationaliSDNNumber $
  l $ physicalDeliveryOfficeName $ postOfficeBox $ postalAddress $ postalCode $
  preferredDeliveryMethod $ registeredAddress $ searchGuide $ seeAlso $ st $
  street $ telephoneNumber $ teletexTerminalIdentifier $ telexNumber $
  userPassword $ x121Address ) X-ORIGIN 'RFC 1274' )
objectClasses: ( 0.9.2342.19200300.100.4.20 NAME 'pilotOrganization'
  SUP ( organization $ organizationalUnit ) STRUCTURAL
  MAY buildingName X-ORIGIN 'RFC 1274' )
objectClasses: ( 0.9.2342.19200300.100.4.15 NAME 'dNSDomain' SUP domain
  MAY ( ARecord $ MDRecord $ MXRecord $ NSRecord $ SOARecord $ CNAMERecord )
  X-ORIGIN 'RFC 1274' )
opends/src/guitools/org/opends/guitools/controlpanel/browser/AbstractNodeTask.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.browser;
@@ -70,7 +70,7 @@
   * @return <CODE>true</CODE> if the operation is cancelled and
   * <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled() {
  public boolean isCanceled() {
    return cancelled;
  }
opends/src/guitools/org/opends/guitools/controlpanel/browser/NodeRefresher.java
@@ -934,7 +934,7 @@
        tax = new SearchAbandonException(State.FAILED, x, null);
      }
    }
    else if (isCancelled()) {
    else if (isCanceled()) {
      tax = new SearchAbandonException(State.CANCELLED, null, null);
    }
    if (tax != null) {
opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java
@@ -846,7 +846,7 @@
          oc1.getObjectClassType(), oc2.getObjectClassType(),
          oc1.getOptionalAttributes(), oc2.getOptionalAttributes(),
          oc1.getRequiredAttributes(), oc2.getRequiredAttributes(),
          oc1.getSuperiorClass(), oc2.getSuperiorClass()
          oc1.getSuperiorClasses(), oc2.getSuperiorClasses()
      };
      for (int i=0; i<compareWithEqual.length && areEqual; i++)
opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedEvent.java
New file
@@ -0,0 +1,79 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.event;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.opends.server.types.ObjectClass;
/**
 * This is the event sent to notify the changes made in the superiors of a given
 * object class.  It is used mainly by the
 * {@link
 * org.opends.guitools.controlpanel.components.SuperiorObjectClassesEditor}
 * class.  It is linked to the {@link SuperiorObjectClassesChangedListener}
 * interface.
 *
 */
public class SuperiorObjectClassesChangedEvent
{
  private Object source;
  private Set<ObjectClass> newObjectClasses = new HashSet<ObjectClass>();
  /**
   * Constructor of the event.
   * @param source the source of the event.
   * @param newObjectClasses the set of new superior object classes.
   */
  public SuperiorObjectClassesChangedEvent(Object source,
      Set<ObjectClass> newObjectClasses)
  {
    this.source = source;
    this.newObjectClasses.addAll(newObjectClasses);
  }
  /**
   * Returns the source of the object.
   * @return the source of the object.
   */
  public Object getSource()
  {
    return source;
  }
  /**
   * Returns the new superior object classes.
   * @return the new superior object classes.
   */
  public Set<ObjectClass> getNewObjectClasses()
  {
    return Collections.unmodifiableSet(newObjectClasses);
  }
}
opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedListener.java
New file
@@ -0,0 +1,45 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.event;
/**
 * This is the listener that receives events about the changes made in the
 * superiors of a given object class.  It is used mainly by the
 * {@link
 * org.opends.guitools.controlpanel.components.SuperiorObjectClassesEditor}
 * class.
 *
 */
public interface SuperiorObjectClassesChangedListener
{
  /**
   * Method called to notify the listener that a change has been made in the
   * superiors of an object class.
   * @param ev the event describing the new superior object classes.
   */
  void parentObjectClassesChanged(SuperiorObjectClassesChangedEvent ev);
}
opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.task;
@@ -648,21 +648,27 @@
      }
    }
    boolean hasSuperior = false;
    ObjectClass newSuperior = ocToDelete.getSuperiorClass();
    for (ObjectClass oc : providedOcsToDelete)
    Set<ObjectClass> newSuperiors = new LinkedHashSet<ObjectClass>();
    for(ObjectClass sup : ocToDelete.getSuperiorClasses())
    {
      if (ocToDelete.getSuperiorClass().equals(oc))
      boolean isFound = false;
      for(ObjectClass oc: providedOcsToDelete)
      {
        hasSuperior = true;
        newSuperior = oc.getSuperiorClass();
        while (newSuperior != null &&
            providedOcsToDelete.contains(newSuperior))
        if(sup.equals(oc))
        {
          newSuperior = newSuperior.getSuperiorClass();
          hasSuperior = true;
          isFound = true;
          newSuperiors.add(getNewSuperior(oc));
          break;
        }
        break;
      }
      if(!isFound)
      {
        //Use the same super if not found in the list.
        newSuperiors.add(sup);
      }
    }
    if (containsAttribute || hasSuperior)
    {
      ArrayList<String> allNames = new ArrayList<String>();
@@ -693,7 +699,7 @@
          allNames,
          ocToDelete.getOID(),
          ocToDelete.getDescription(),
          newSuperior,
          newSuperiors,
          required,
          optional,
          ocToDelete.getObjectClassType(),
@@ -709,6 +715,25 @@
  }
  private ObjectClass getNewSuperior(ObjectClass currentSup)
  {
    if(currentSup.getSuperiorClasses() == null ||
            currentSup.getSuperiorClasses().isEmpty())
     {
       return currentSup;
     }
     if(providedOcsToDelete.contains(currentSup))
     {
      for(ObjectClass o : currentSup.getSuperiorClasses())
      {
       return getNewSuperior(o);
      }
     }
     return null;
  }
  /**
   * Returns an ordered set of the attributes that must be deleted.
   * @param attrsToDelete the attributes to be deleted.
@@ -828,7 +853,7 @@
    LinkedHashSet<ObjectClass> children = new LinkedHashSet<ObjectClass>();
    for (ObjectClass oc : schema.getObjectClasses().values())
    {
      if (objectClass.equals(oc.getSuperiorClass()))
      if (oc.getSuperiorClasses().contains(objectClass))
      {
        children.addAll(getOrderedChildrenToDelete(oc, schema));
        children.add(oc);
opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.task;
@@ -242,7 +242,7 @@
          allNames,
          ocToDelete.getOID(),
          ocToDelete.getDescription(),
          ocToDelete.getSuperiorClass(),
          ocToDelete.getSuperiorClasses(),
          required,
          optional,
          ocToDelete.getObjectClassType(),
opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.task;
@@ -164,11 +164,12 @@
  private ObjectClass getObjectClassToAdd(ObjectClass ocToDelete)
  {
    ObjectClass ocToAdd;
    Set<ObjectClass> currentSups = ocToDelete.getSuperiorClasses();
    if (ocToDelete.equals(oldObjectClass))
    {
      ocToAdd = newObjectClass;
    }
    else if (oldObjectClass.equals(ocToDelete.getSuperiorClass()))
    else if (currentSups.contains(oldObjectClass))
    {
      ArrayList<String> allNames = new ArrayList<String>();
      for (String str : ocToDelete.getNormalizedNames())
@@ -177,13 +178,24 @@
      }
      Map<String, List<String>> extraProperties =
        DeleteSchemaElementsTask.cloneExtraProperties(ocToDelete);
      Set<ObjectClass> newSups = new LinkedHashSet<ObjectClass>();
      for(ObjectClass oc: currentSups)
      {
        if(oc.equals(oldObjectClass))
        {
          newSups.add(newObjectClass);
        }
        else
        {
          newSups.add(oc);
        }
      }
      ocToAdd = new ObjectClass("",
          ocToDelete.getPrimaryName(),
          allNames,
          ocToDelete.getOID(),
          ocToDelete.getDescription(),
          newObjectClass,
          newSups,
          ocToDelete.getRequiredAttributes(),
          ocToDelete.getOptionalAttributes(),
          ocToDelete.getObjectClassType(),
opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
@@ -1492,14 +1492,7 @@
        mustAdd = false;
        for (ObjectClass o : lastSchema.getObjectClasses().values())
        {
          boolean isChild = false;
          ObjectClass parent = o.getSuperiorClass();
          while (!isChild && (parent != null))
          {
            isChild = parent == oc;
            parent = parent.getSuperiorClass();
          }
          if (isChild)
          if (isDescendant(oc, o))
          {
            mustAdd = mustAddObjectClassName(o, f);
            if (mustAdd)
@@ -1511,13 +1504,7 @@
      }
      else if (PARENT_CLASS.equals(filterType))
      {
        mustAdd = false;
        ObjectClass parentClass = oc.getSuperiorClass();
        while (!mustAdd && (parentClass != null))
        {
          mustAdd = mustAddObjectClassName(parentClass, f);
          parentClass = parentClass.getSuperiorClass();
        }
        mustAdd = mustAddParentObjectClassName(oc, f);
      }
      else
      {
@@ -1527,6 +1514,50 @@
    return mustAdd;
  }
  private boolean mustAddParentObjectClassName(ObjectClass oc, String f)
  {
    boolean mustAdd = false;
    Set<ObjectClass> parents = oc.getSuperiorClasses();
    for (ObjectClass parent : parents)
    {
      if (mustAddObjectClassName(parent, f) ||
          mustAddParentObjectClassName(parent, f))
      {
        mustAdd = true;
        break;
      }
    }
    return mustAdd;
  }
  /**
   * Finds out if a class is descendant of another class using equality of
   * pointers.
   * @param ocParent the parent object class.
   * @param oChild the (potentially) descendant object class.
   * @return {@code true} if the class is a descendant of the parent class
   * and {@code false} otherwise.
   */
  private boolean isDescendant(ObjectClass ocParent, ObjectClass oChild)
  {
    Set<ObjectClass> superiors = oChild.getSuperiorClasses();
    if (superiors == null || superiors.isEmpty())
    {
      return false;
    }
    else
    {
      for (ObjectClass o : oChild.getSuperiorClasses())
      {
        if (ocParent == o || isDescendant(ocParent, o))
        {
          return true;
        }
      }
    }
    return false;
  }
  /**
   * Check whether the provided matching rule must be added or not.
   * @param matchingRule the matching rule.
@@ -1759,17 +1790,9 @@
      int index = -1;
      for (int i=0; i<lOrderedOcs.size(); i++)
      {
        ObjectClass parent = lOrderedOcs.get(i).getSuperiorClass();
        while ((parent != null) && (index == -1))
        if (lOrderedOcs.get(i).isDescendantOf(oc))
        {
          if (parent.equals(oc))
          {
            index = i+1;
          }
          else
          {
            parent = parent.getSuperiorClass();
          }
          index = i+1;
        }
      }
      if (index == -1)
@@ -1830,7 +1853,7 @@
    {
      for (ObjectClass o : schema.getObjectClasses().values())
      {
        if (objectClass.equals(o.getSuperiorClass()))
        if (o.getSuperiorClasses().contains(objectClass))
        {
          childClasses.add(o);
        }
opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
@@ -502,7 +502,7 @@
    }
    operationViewPanel.setSelectedAttributes(chOperations);
    operationViewDlg.setVisible(true);
    if (!operationViewPanel.isCancelled())
    if (!operationViewPanel.isCanceled())
    {
      boolean showAverages = showAveragesMenu.isSelected();
      chOperations = operationViewPanel.getAttributes();
opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java
@@ -36,11 +36,10 @@
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@@ -48,8 +47,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
@@ -74,16 +71,20 @@
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.event.
 ConfigurationElementCreatedListener;
import org.opends.guitools.controlpanel.event.SuperiorObjectClassesChangedEvent;
import org.opends.guitools.controlpanel.event.
 SuperiorObjectClassesChangedListener;
import org.opends.guitools.controlpanel.event.ScrollPaneBorderListener;
import org.opends.guitools.controlpanel.task.DeleteSchemaElementsTask;
import org.opends.guitools.controlpanel.task.ModifyObjectClassTask;
import org.opends.guitools.controlpanel.task.Task;
import org.opends.guitools.controlpanel.ui.components.BasicExpander;
import org.opends.guitools.controlpanel.ui.components.DoubleAddRemovePanel;
import org.opends.guitools.controlpanel.ui.components.
 SuperiorObjectClassesEditor;
import org.opends.guitools.controlpanel.ui.components.TitlePanel;
import org.opends.guitools.controlpanel.ui.renderer.
 SchemaElementComboBoxCellRenderer;
import org.opends.guitools.controlpanel.util.LowerCaseComparator;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
@@ -110,7 +111,7 @@
  private TitlePanel titlePanel = new TitlePanel(Message.EMPTY, Message.EMPTY);
  private JLabel lName = Utilities.createPrimaryLabel(
      INFO_CTRL_PANEL_OBJECTCLASS_NAME_LABEL.get());
  private JLabel lParent = Utilities.createPrimaryLabel(
  private JLabel lSuperior = Utilities.createPrimaryLabel(
      INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get());
  private JLabel lOID = Utilities.createPrimaryLabel(
      INFO_CTRL_PANEL_OBJECTCLASS_OID_LABEL.get());
@@ -133,12 +134,13 @@
  private Set<AttributeType> inheritedRequiredAttributes =
    new HashSet<AttributeType>();
  private JLabel[] labels = {lName, lParent, lOID, lAliases, lOrigin, lFile,
  private JLabel[] labels = {lName, lSuperior, lOID, lAliases, lOrigin, lFile,
      lDescription, lType, lAttributes
  };
  private JTextField name = Utilities.createMediumTextField();
  private JComboBox parent = Utilities.createComboBox();
  private SuperiorObjectClassesEditor superiors =
    new SuperiorObjectClassesEditor();
  private JComboBox type = Utilities.createComboBox();
  private JTextField oid = Utilities.createMediumTextField();
  private JTextField description = Utilities.createLongTextField();
@@ -241,31 +243,41 @@
   */
  protected void createBasicLayout(Container c, GridBagConstraints gbc)
  {
    SchemaElementComboBoxCellRenderer renderer = new
    SchemaElementComboBoxCellRenderer(parent);
    DefaultComboBoxModel model = new DefaultComboBoxModel();
    parent.setModel(model);
    parent.setRenderer(renderer);
    ItemListener itemListener = new ItemListener()
    SuperiorObjectClassesChangedListener listener =
      new SuperiorObjectClassesChangedListener()
    {
      /**
       * {@inheritDoc}
       */
      public void itemStateChanged(ItemEvent ev)
      public void parentObjectClassesChanged(
          SuperiorObjectClassesChangedEvent ev)
      {
        if (ignoreChangeEvents) return;
        updateAttributesWithParent(true);
        checkEnableSaveChanges();
        if (ev.getNewObjectClasses().size() > 1)
        {
          lSuperior.setText(
              INFO_CTRL_PANEL_OBJECTCLASS_PARENTS_LABEL.get().toString());
        }
        else
        {
          lSuperior.setText(
              INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get().toString());
        }
      }
    };
    parent.addItemListener(itemListener);
    superiors.addParentObjectClassesChangedListener(listener);
    model = new DefaultComboBoxModel();
    DefaultComboBoxModel model = new DefaultComboBoxModel();
    for (ObjectClassType t : ObjectClassType.values())
    {
      model.addElement(t);
    }
    type.setModel(model);
    type.setSelectedItem(ObjectClassType.STRUCTURAL);
    SchemaElementComboBoxCellRenderer renderer = new
    SchemaElementComboBoxCellRenderer(type);
    type.setRenderer(renderer);
    attributes =
@@ -303,8 +315,8 @@
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    Component[] basicComps = {name, oid, description, parent};
    JLabel[] basicLabels = {lName, lOID, lDescription, lParent};
    Component[] basicComps = {name, oid, description, superiors};
    JLabel[] basicLabels = {lName, lOID, lDescription, lSuperior};
    JLabel[] basicInlineHelp = new JLabel[] {null, null, null, null};
    add(basicLabels, basicComps, basicInlineHelp, c, gbc);
@@ -425,11 +437,7 @@
      }
    };
    JComboBox[] combos = {parent, type};
    for (JComboBox combo : combos)
    {
      combo.addActionListener(actionListener);
    }
    type.addActionListener(actionListener);
    ListDataListener dataListener = new ListDataListener()
    {
@@ -497,7 +505,18 @@
    modelRequired.clear();
    modelAvailable.clear();
    parent.setSelectedItem(oc.getSuperiorClass());
    superiors.setSelectedSuperiors(oc.getSuperiorClasses());
    superiors.setObjectClassesToExclude(Collections.singleton(oc));
    if (oc.getSuperiorClasses().size() > 1)
    {
      lSuperior.setText(
          INFO_CTRL_PANEL_OBJECTCLASS_PARENTS_LABEL.get().toString());
    }
    else
    {
      lSuperior.setText(
          INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get().toString());
    }
    updateAttributesWithParent(false);
@@ -582,33 +601,6 @@
    {
      schema = s;
      HashMap<String, ObjectClass> objectClassNameMap = new HashMap<String,
      ObjectClass>();
      for (String key : schema.getObjectClasses().keySet())
      {
        ObjectClass oc = schema.getObjectClass(key);
        objectClassNameMap.put(oc.getNameOrOID(), oc);
      }
      SortedSet<String> orderedKeys =
        new TreeSet<String>(new LowerCaseComparator());
      orderedKeys.addAll(objectClassNameMap.keySet());
      ArrayList<ObjectClass> newParents = new ArrayList<ObjectClass>();
      for (String key : orderedKeys)
      {
        newParents.add(objectClassNameMap.get(key));
      }
      updateComboBoxModel(newParents,
          ((DefaultComboBoxModel)parent.getModel()), new Comparator<Object>()
      {
        /**
         * {@inheritDoc}
         */
        public int compare(Object arg0, Object arg1)
        {
          return String.valueOf(arg0).compareTo(String.valueOf(arg1));
        }
      });
      updateErrorPaneIfAuthRequired(desc,
          isLocal() ?
        INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_OBJECTCLASS_EDIT.get() :
@@ -637,8 +629,9 @@
            !authenticationRequired(desc)
            && !authenticationRequired(desc)
            && schema != null);
        if (schemaChanged)
        if (schemaChanged && schema != null)
        {
          superiors.setSchema(schema);
          updateAttributes();
        }
      }
@@ -720,9 +713,12 @@
    {
      for (ObjectClass o : schema.getObjectClasses().values())
      {
        if (objectClass.equals(o.getSuperiorClass()))
        for (ObjectClass superior : o.getSuperiorClasses())
        {
          childClasses.add(o.getNameOrOID());
          if (objectClass.equals(superior))
          {
            childClasses.add(o.getNameOrOID());
          }
        }
      }
    }
@@ -858,33 +854,13 @@
    }
    ObjectClass superior = getSuperior();
    if (superior != null)
   //validate the superiority.
    for(ObjectClass superior : getObjectClassSuperiors())
    {
      if (superior.getNameOrOID().equalsIgnoreCase(objectClass.getNameOrOID()))
      {
        errors.add(ERR_CTRL_PANEL_OBJECTCLASS_CANNOT_BE_ITS_SUPERIOR.get());
        setPrimaryInvalid(lParent);
      }
      else
      {
        // Check whether this object class is defined as parent as the superior.
        superior = superior.getSuperiorClass();
        while (superior != null)
        {
          if (superior.getNameOrOID().equalsIgnoreCase(
              objectClass.getNameOrOID()))
          {
            errors.add(
                ERR_CTRL_PANEL_OBJECTCLASS_IS_SUPERIOR_OF_SUPERIOR.get(
                getSuperior().getNameOrOID()));
            setPrimaryInvalid(lParent);
            break;
          }
          superior = superior.getSuperiorClass();
        }
      }
      validateSuperiority(superior, errors);
    }
    checkCompatibleSuperiors(getObjectClassSuperiors(), getObjectClassType(),
        errors);
    if (errors.size() == 0)
    {
@@ -924,6 +900,30 @@
    }
  }
  private void validateSuperiority(ObjectClass superior,
          ArrayList<Message> errors)
  {
    if(superior.getNameOrOID().equalsIgnoreCase(objectClass.getNameOrOID()))
    {
      errors.add(ERR_CTRL_PANEL_OBJECTCLASS_CANNOT_BE_ITS_SUPERIOR.get());
      setPrimaryInvalid(lSuperior);
      return;
    }
    for (ObjectClass obj : superior.getSuperiorClasses())
    {
      if (superior.getNameOrOID().equalsIgnoreCase(obj.getNameOrOID()))
      {
         errors.add(
                ERR_CTRL_PANEL_OBJECTCLASS_IS_SUPERIOR_OF_SUPERIOR.get(
                obj.getNameOrOID()));
            setPrimaryInvalid(lSuperior);
        return;
      }
      validateSuperiority(obj,errors);
    }
  }
  private void checkEnableSaveChanges()
  {
    if (ignoreChangeEvents) return;
@@ -1011,9 +1011,9 @@
    return description.getText().trim();
  }
  private ObjectClass getSuperior()
  private Set<ObjectClass> getObjectClassSuperiors()
  {
    return (ObjectClass)parent.getSelectedItem();
    return superiors.getSelectedSuperiors();
  }
  private ObjectClassType getObjectClassType()
@@ -1044,7 +1044,7 @@
        getAllNames(),
        getOID(),
        getDescription(),
        getSuperior(),
        getObjectClassSuperiors(),
        getRequiredAttributes(),
        getOptionalAttributes(),
        getObjectClassType(),
@@ -1148,8 +1148,7 @@
    inheritedOptionalAttributes.clear();
    inheritedRequiredAttributes.clear();
    ObjectClass p = (ObjectClass)parent.getSelectedItem();
    if (p != null)
    for (ObjectClass p : getObjectClassSuperiors())
    {
      for (AttributeType attr : p.getRequiredAttributeChain())
      {
opends/src/guitools/org/opends/guitools/controlpanel/ui/DBEnvironmentMonitoringPanel.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
@@ -236,7 +236,7 @@
    }
    operationViewPanel.setSelectedAttributes(attributes);
    operationViewDlg.setVisible(true);
    if (!operationViewPanel.isCancelled())
    if (!operationViewPanel.isCanceled())
    {
      attributes = operationViewPanel.getAttributes();
      setOperationsToDisplay(attributes);
opends/src/guitools/org/opends/guitools/controlpanel/ui/MainMenuBar.java
@@ -238,7 +238,7 @@
          Utilities.getFrame(MainMenuBar.this));
    }
    dlg.setVisible(true);
    if (!panel.isCancelled())
    if (!panel.isCanceled())
    {
      getInfo().setPoolingPeriod(panel.getPoolingPeriod());
      getInfo().stopPooling();
opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java
@@ -894,7 +894,7 @@
    operationViewPanel.setSelectedAttributes(
        tableModel.getDisplayedAttributes());
    operationViewDlg.setVisible(true);
    if (!operationViewPanel.isCancelled())
    if (!operationViewPanel.isCanceled())
    {
      LinkedHashSet<Message> displayedAttributes =
        operationViewPanel.getAttributes();
opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java
@@ -67,7 +67,7 @@
 private LinkedHashSet<T> monitoringAttributes;
 private boolean isCancelled = true;
 private boolean isCanceled = true;
 // Note: the order of the checkboxes and the elements in the Attributes
 // enumeration will be the same.
@@ -293,7 +293,7 @@
 {
   if (visible)
   {
     isCancelled = true;
     isCanceled = true;
   }
 }
@@ -321,7 +321,7 @@
   }
   else
   {
     isCancelled = false;
     isCanceled = false;
     super.closeClicked();
   }
 }
@@ -340,9 +340,9 @@
  * @return <CODE>true</CODE> if the user closed the dialog by cancelling it
  * and <CODE>false</CODE> otherwise.
  */
 public boolean isCancelled()
 public boolean isCanceled()
 {
   return isCancelled;
   return isCanceled;
 }
 /**
opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java
@@ -32,11 +32,10 @@
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@@ -44,8 +43,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
@@ -63,13 +60,17 @@
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.event.
 ConfigurationElementCreatedListener;
import org.opends.guitools.controlpanel.event.SuperiorObjectClassesChangedEvent;
import org.opends.guitools.controlpanel.event.
 SuperiorObjectClassesChangedListener;
import org.opends.guitools.controlpanel.task.NewSchemaElementsTask;
import org.opends.guitools.controlpanel.task.Task;
import org.opends.guitools.controlpanel.ui.components.BasicExpander;
import org.opends.guitools.controlpanel.ui.components.DoubleAddRemovePanel;
import org.opends.guitools.controlpanel.ui.components.
 SuperiorObjectClassesEditor;
import
org.opends.guitools.controlpanel.ui.renderer.SchemaElementComboBoxCellRenderer;
import org.opends.guitools.controlpanel.util.LowerCaseComparator;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
@@ -91,7 +92,7 @@
 private static final long serialVersionUID = -4956885827963184571L;
  private JLabel lName = Utilities.createPrimaryLabel(
      INFO_CTRL_PANEL_OBJECTCLASS_NAME_LABEL.get());
  private JLabel lParent = Utilities.createPrimaryLabel(
  private JLabel lSuperior = Utilities.createPrimaryLabel(
      INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get());
  private JLabel lOID = Utilities.createPrimaryLabel(
      INFO_CTRL_PANEL_OBJECTCLASS_OID_LABEL.get());
@@ -114,12 +115,13 @@
  private Set<AttributeType> inheritedRequiredAttributes =
    new HashSet<AttributeType>();
  private JLabel[] labels = {lName, lParent, lOID, lAliases, lOrigin, lFile,
  private JLabel[] labels = {lName, lSuperior, lOID, lAliases, lOrigin, lFile,
      lDescription, lType, lAttributes
  };
  private JTextField name = Utilities.createMediumTextField();
  private JComboBox parent = Utilities.createComboBox();
  private SuperiorObjectClassesEditor superiors = new
  SuperiorObjectClassesEditor();
  private JComboBox type = Utilities.createComboBox();
  private JTextField oid = Utilities.createMediumTextField();
  private JTextField description = Utilities.createLongTextField();
@@ -169,8 +171,7 @@
    final ServerDescriptor desc = ev.getNewDescriptor();
    Schema s = desc.getSchema();
    final boolean firstSchema = schema == null;
    final boolean[] repack = {firstSchema};
    final boolean[] repack = {schema == null};
    final boolean[] error = {false};
    final boolean schemaChanged;
@@ -193,26 +194,8 @@
    if (schemaChanged)
    {
      schema = s;
      HashMap<String, ObjectClass> objectClassNameMap = new HashMap<String,
      ObjectClass>();
      for (String key : schema.getObjectClasses().keySet())
      {
        ObjectClass oc = schema.getObjectClass(key);
        objectClassNameMap.put(oc.getNameOrOID(), oc);
      }
      SortedSet<String> orderedKeys =
        new TreeSet<String>(new LowerCaseComparator());
      orderedKeys.addAll(objectClassNameMap.keySet());
      ArrayList<Object> newParents = new ArrayList<Object>();
      for (String key : orderedKeys)
      {
        newParents.add(objectClassNameMap.get(key));
      }
      updateComboBoxModel(newParents,
          ((DefaultComboBoxModel)parent.getModel()));
    }
    else
    else if (schema == null)
    {
      updateErrorPane(errorPane,
          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
@@ -230,12 +213,9 @@
        errorPane.setVisible(error[0]);
        if (schema != null)
        {
          if (firstSchema)
          {
            parent.setSelectedItem(schema.getObjectClass("top"));
          }
          if (schemaChanged)
          {
            superiors.setSchema(schema);
            updateAttributes();
          }
        }
@@ -335,6 +315,9 @@
      }
    }
    checkCompatibleSuperiors(getObjectClassSuperiors(), getObjectClassType(),
        errors);
    ProgressDialog dlg = new ProgressDialog(
        Utilities.createFrame(),
        Utilities.getParentDialog(this),
@@ -373,6 +356,14 @@
      oid.setText("");
      description.setText("");
      aliases.setText("");
      superiors.setSelectedSuperiors(
          Collections.singleton(schema.getObjectClass("top")));
      attributes.getAvailableListModel().addAll(
          attributes.getSelectedListModel1().getData());
      attributes.getAvailableListModel().addAll(
          attributes.getSelectedListModel2().getData());
      attributes.getSelectedListModel1().clear();
      attributes.getSelectedListModel2().clear();
      name.grabFocus();
      Utilities.getParentDialog(this).setVisible(false);
    }
@@ -488,17 +479,14 @@
    gbc.anchor = GridBagConstraints.WEST;
    gbc.insets.bottom = 0;
    SchemaElementComboBoxCellRenderer renderer = new
    SchemaElementComboBoxCellRenderer(parent);
    DefaultComboBoxModel model = new DefaultComboBoxModel();
    parent.setModel(model);
    parent.setRenderer(renderer);
    ItemListener itemListener = new ItemListener()
    SuperiorObjectClassesChangedListener listener =
      new SuperiorObjectClassesChangedListener()
    {
      /**
       * {@inheritDoc}
       */
      public void itemStateChanged(ItemEvent ev)
      public void parentObjectClassesChanged(
          SuperiorObjectClassesChangedEvent ev)
      {
        // Remove the previous inherited attributes.
        for (AttributeType attr : inheritedRequiredAttributes)
@@ -514,18 +502,16 @@
        inheritedOptionalAttributes.clear();
        inheritedRequiredAttributes.clear();
        ObjectClass p = (ObjectClass)parent.getSelectedItem();
        while (p != null)
        for (ObjectClass oc : superiors.getSelectedSuperiors())
        {
          for (AttributeType attr : p.getRequiredAttributeChain())
          for (AttributeType attr : oc.getRequiredAttributeChain())
          {
            inheritedRequiredAttributes.add(attr);
          }
          for (AttributeType attr : p.getOptionalAttributeChain())
          for (AttributeType attr : oc.getOptionalAttributeChain())
          {
            inheritedOptionalAttributes.add(attr);
          }
          p = p.getSuperiorClass();
        }
        for (AttributeType attr : inheritedRequiredAttributes)
        {
@@ -551,17 +537,30 @@
          new ArrayList<AttributeType>(inheritedRequiredAttributes);
        unmovableItems.addAll(inheritedOptionalAttributes);
        attributes.setUnmovableItems(unmovableItems);
        if (ev.getNewObjectClasses().size() > 1)
        {
          lSuperior.setText(
              INFO_CTRL_PANEL_OBJECTCLASS_PARENTS_LABEL.get().toString());
        }
        else
        {
          lSuperior.setText(
              INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get().toString());
        }
      }
    };
    parent.addItemListener(itemListener);
    superiors.addParentObjectClassesChangedListener(listener);
    model = new DefaultComboBoxModel();
    DefaultComboBoxModel model = new DefaultComboBoxModel();
    for (ObjectClassType t : ObjectClassType.values())
    {
      model.addElement(t);
    }
    type.setModel(model);
    type.setSelectedItem(ObjectClassType.STRUCTURAL);
    SchemaElementComboBoxCellRenderer renderer = new
    SchemaElementComboBoxCellRenderer(type);
    type.setRenderer(renderer);
    attributes =
@@ -581,8 +580,8 @@
    attributes.getSelectedListModel1().setComparator(comparator);
    attributes.getSelectedListModel2().setComparator(comparator);
    Component[] basicComps = {name, oid, description, parent};
    JLabel[] basicLabels = {lName, lOID, lDescription, lParent};
    Component[] basicComps = {name, oid, description, superiors};
    JLabel[] basicLabels = {lName, lOID, lDescription, lSuperior};
    JLabel[] basicInlineHelp = new JLabel[] {null, null, null, null};
    add(basicLabels, basicComps, basicInlineHelp, this, gbc);
@@ -681,9 +680,9 @@
    return o;
  }
  private ObjectClass getSuperior()
  private Set<ObjectClass> getObjectClassSuperiors()
  {
    return (ObjectClass)parent.getSelectedItem();
    return superiors.getSelectedSuperiors();
  }
  private Map<String, List<String>> getExtraProperties()
@@ -739,7 +738,7 @@
    ObjectClass oc = new ObjectClass("", getObjectClassName(), getAllNames(),
        getOID(),
        getDescription(),
        getSuperior(),
        getObjectClassSuperiors(),
        getRequiredAttributes(),
        getOptionalAttributes(),
        getObjectClassType(),
opends/src/guitools/org/opends/guitools/controlpanel/ui/RefreshOptionsPanel.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
@@ -51,7 +51,7 @@
  private JTextField period;
  private JLabel lPeriod;
  private boolean isCancelled = true;
  private boolean isCanceled = true;
  private int MAX_VALUE = 5000;
@@ -143,7 +143,7 @@
   */
  public void okClicked()
  {
    isCancelled = true;
    isCanceled = true;
    setPrimaryValid(lPeriod);
    LinkedHashSet<Message> errors = new LinkedHashSet<Message>();
@@ -166,7 +166,7 @@
    }
    else
    {
      isCancelled = false;
      isCanceled = false;
      Utilities.getParentDialog(this).setVisible(false);
    }
  }
@@ -175,9 +175,9 @@
   * Returns whether this dialog has been cancelled or not.
   * @return whether this dialog has been cancelled or not.
   */
  public boolean isCancelled()
  public boolean isCanceled()
  {
    return isCancelled;
    return isCanceled;
  }
  /**
@@ -187,7 +187,7 @@
  {
    if (visible)
    {
      isCancelled = true;
      isCanceled = true;
      long timeInSeconds = getInfo().getPoolingPeriod() / 1000;
      period.setText(String.valueOf(timeInSeconds));
    }
opends/src/guitools/org/opends/guitools/controlpanel/ui/SelectObjectClassesPanel.java
New file
@@ -0,0 +1,291 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
import static org.opends.messages.AdminToolMessages.*;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JEditorPane;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.ui.components.AddRemovePanel;
import org.opends.guitools.controlpanel.ui.renderer.
 SchemaElementComboBoxCellRenderer;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Schema;
/**
 * This is a class where the user can choose from a list of available object
 * classes one or more object classes.
 *
 */
public class SelectObjectClassesPanel extends StatusGenericPanel
{
  private static final long serialVersionUID = 1230982500028334L;
  private AddRemovePanel<ObjectClass> addRemove =
    new AddRemovePanel<ObjectClass>(ObjectClass.class);
  private Set<ObjectClass> toExclude = new HashSet<ObjectClass>();
  private Schema schema;
  private boolean isCanceled = true;
  /**
   * Default constructor of this panel.
   */
  public SelectObjectClassesPanel()
  {
    createLayout();
  }
  private void createLayout()
  {
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.WEST;
    gbc.weightx = 0.0;
    gbc.gridx = 0;
    gbc.gridy = 0;
    JEditorPane instructions = Utilities.makePlainTextPane(
        INFO_CTRL_PANEL_SUPERIOR_OBJECTCLASSES_INSTRUCTIONS.get().toString(),
        ColorAndFontConstants.defaultFont);
    gbc.weightx = 1.0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    add(instructions, gbc);
    gbc.gridy ++;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.weightx = 1.0;
    gbc.weighty = 1.0;
    addRemove.getAvailableLabel().setText(
        INFO_CTRL_PANEL_ADDREMOVE_AVAILABLE_OBJECTCLASSES.get().toString());
    addRemove.getSelectedLabel().setText(
        INFO_CTRL_PANEL_ADDREMOVE_SELECTED_OBJECTCLASSES.get().toString());
    Comparator<ObjectClass> comparator = new Comparator<ObjectClass>()
    {
      /**
       * {@inheritDoc}
       */
      public int compare(ObjectClass oc1, ObjectClass oc2)
      {
        return oc1.getNameOrOID().toLowerCase().compareTo(
            oc2.getNameOrOID().toLowerCase());
      }
    };
    addRemove.getAvailableListModel().setComparator(comparator);
    addRemove.getSelectedListModel().setComparator(comparator);
    SchemaElementComboBoxCellRenderer renderer =
      new SchemaElementComboBoxCellRenderer(addRemove.getAvailableList());
    addRemove.getAvailableList().setCellRenderer(renderer);
    renderer =
      new SchemaElementComboBoxCellRenderer(addRemove.getSelectedList());
    addRemove.getSelectedList().setCellRenderer(renderer);
    gbc.insets.top = 10;
    add(addRemove, gbc);
  }
  /**
   * {@inheritDoc}
   */
  public Component getPreferredFocusComponent()
  {
    return addRemove;
  }
  /**
   * {@inheritDoc}
   */
  public Message getTitle()
  {
    return INFO_CTRL_PANEL_SUPERIOR_OBJECTCLASSES_TITLE.get();
  }
  /**
   * {@inheritDoc}
   */
  public void okClicked()
  {
    isCanceled = true;
    Set<ObjectClass> selectedObjectClasses =
      addRemove.getSelectedListModel().getData();
    if (selectedObjectClasses.isEmpty())
    {
      displayErrorMessage(INFO_CTRL_PANEL_ERROR_DIALOG_TITLE.get(),
          INFO_CTRL_PANEL_ERROR_NO_SUPERIOR_SELECTED.get());
    }
    else
    {
      isCanceled = false;
      closeClicked();
    }
  }
  /**
   * Returns whether this dialog has been canceled or not.
   * @return whether this dialog has been canceled or not.
   */
  public boolean isCanceled()
  {
    return isCanceled;
  }
  /**
   * {@inheritDoc}
   */
  public void toBeDisplayed(boolean visible)
  {
    if (visible)
    {
      isCanceled = true;
    }
  }
  /**
   * {@inheritDoc}
   */
  public void configurationChanged(ConfigurationChangeEvent ev)
  {
  }
  /**
   * Returns the selected object classes.
   * @return the selected object classes.
   */
  public Set<ObjectClass> getSelectedObjectClasses()
  {
    return addRemove.getSelectedListModel().getData();
  }
  /**
   * Sets the selected object classes.
   * @param selectedObjectClasses the selected object classes.
   */
  public void setSelectedObjectClasses(Set<ObjectClass> selectedObjectClasses)
  {
    Set<ObjectClass> toAdd = new HashSet<ObjectClass>();
    Set<ObjectClass> previouslySelected =
      addRemove.getSelectedListModel().getData();
    for (ObjectClass oc : previouslySelected)
    {
      if (!selectedObjectClasses.contains(oc))
      {
        addRemove.getSelectedListModel().remove(oc);
        toAdd.add(oc);
      }
    }
    addRemove.getAvailableListModel().addAll(toAdd);
    for (ObjectClass oc : selectedObjectClasses)
    {
      if (!previouslySelected.contains(oc))
      {
        addRemove.getSelectedListModel().add(oc);
      }
      addRemove.getAvailableListModel().remove(oc);
    }
    fireAddRemoveNotifications();
  }
  /**
   * Sets the list of object classes that this panel should not display
   * (mainly used to not display the object class for which we are editing
   * the superior object classes).
   * @param toExclude the list of object classes to exclude.
   */
  public void setObjectClassesToExclude(Set<ObjectClass> toExclude)
  {
    this.toExclude.clear();
    this.toExclude.addAll(toExclude);
    updateWithSchema(schema);
    fireAddRemoveNotifications();
  }
  /**
   * Sets the schema to be used by this panel.
   * @param schema the schema to be used by this panel.
   */
  public void setSchema(Schema schema)
  {
    updateWithSchema(schema);
    fireAddRemoveNotifications();
  }
  private void updateWithSchema(Schema schema)
  {
    ArrayList<ObjectClass> allOcs = new ArrayList<ObjectClass>();
    for (String key : schema.getObjectClasses().keySet())
    {
      ObjectClass oc = schema.getObjectClass(key);
      if (!toExclude.contains(oc))
      {
        allOcs.add(oc);
      }
    }
    for (ObjectClass oc : addRemove.getSelectedListModel().getData())
    {
      if (!allOcs.contains(oc))
      {
        addRemove.getSelectedListModel().remove(oc);
      }
      else
      {
        allOcs.remove(oc);
      }
    }
    addRemove.getAvailableListModel().clear();
    addRemove.getAvailableListModel().addAll(allOcs);
    this.schema = schema;
  }
  /**
   * Returns the list of object classes that this panel will not display.
   * @return the list of object classes that this panel will not display.
   */
  public Set<ObjectClass> getObjectClassToExclude()
  {
    return Collections.unmodifiableSet(toExclude);
  }
  private void fireAddRemoveNotifications()
  {
    addRemove.getSelectedListModel().fireContentsChanged(this, 0,
        addRemove.getSelectedListModel().getSize() - 1);
    addRemove.getAvailableListModel().fireContentsChanged(this, 0,
        addRemove.getAvailableListModel().getSize() - 1);
  }
}
opends/src/guitools/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java
@@ -2022,7 +2022,7 @@
    /**
     * Returns the value that the component is displaying.  The returned value
     * is a Set of Strings (for multivalued attributes), a byte[] for binary
     * is a Set of Strings (for multi-valued attributes), a byte[] for binary
     * values or a String for single-valued attributes.   Single-valued
     * attributes refer to the definition in the schema (and not to the fact
     * that there is a single value for the attribute in this entry).
@@ -2047,12 +2047,7 @@
          ObjectClass oc = schema.getObjectClass(structural.toLowerCase());
          if (oc != null)
          {
            ObjectClass parent = oc.getSuperiorClass();
            while (parent != null)
            {
              values.add(parent.getNameOrOID());
              parent = parent.getSuperiorClass();
            }
            values.addAll(getObjectClassSuperiorValues(oc));
          }
        }
        returnValue = values;
opends/src/guitools/org/opends/guitools/controlpanel/ui/StandardObjectClassPanel.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
@@ -68,6 +68,9 @@
{
  private static final long serialVersionUID = 5561268287795223026L;
  private TitlePanel titlePanel = new TitlePanel(Message.EMPTY, Message.EMPTY);
  private JLabel lParent;
  private JLabel name = Utilities.createDefaultLabel();
  private JLabel parent = Utilities.createDefaultLabel();
  private JLabel oid = Utilities.createDefaultLabel();
@@ -182,6 +185,10 @@
      gbc.insets.left = 0;
      gbc.gridx = 0;
      JLabel l = Utilities.createPrimaryLabel(labels[i]);
      if (i == 1)
      {
        lParent = l;
      }
      c.add(l, gbc);
      gbc.insets.left = 10;
      gbc.gridx = 1;
@@ -309,20 +316,7 @@
    }
    titlePanel.setDetails(Message.raw(n));
    name.setText(n);
    ObjectClass superior = oc.getSuperiorClass();
    if (superior == null)
    {
      n = null;
    }
    else
    {
      n = superior.getPrimaryName();
    }
    if (n == null)
    {
      n = NOT_APPLICABLE.toString();
    }
    parent.setText(n);
    parent.setText(getSuperiorText(oc));
    oid.setText(oc.getOID());
    origin.setText(getOrigin(oc).toString());
    n = oc.getDescription();
@@ -364,13 +358,31 @@
    {
      requiredAttrs.add(attr.getNameOrOID());
    }
    ObjectClass parent = oc.getSuperiorClass();
    if (parent != null)
    Set<ObjectClass> parents = oc.getSuperiorClasses();
    if (parents != null)
    {
      for (AttributeType attr : parent.getRequiredAttributeChain())
      if (parents.size() > 1)
      {
        inheritedAttrs.add(attr.getNameOrOID());
        lParent.setText(
            INFO_CTRL_PANEL_OBJECTCLASS_PARENTS_LABEL.get().toString());
      }
      else
      {
        lParent.setText(
            INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get().toString());
      }
      for (ObjectClass parent : parents)
      {
        for (AttributeType attr : parent.getRequiredAttributeChain())
        {
          inheritedAttrs.add(attr.getNameOrOID());
        }
      }
    }
    else
    {
      lParent.setText(
          INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get().toString());
    }
    DefaultListModel model = (DefaultListModel)requiredAttributes.getModel();
@@ -396,12 +408,14 @@
    {
      optionalAttrs.add(attr.getNameOrOID());
    }
    parent = oc.getSuperiorClass();
    if (parent != null)
    if (parents != null)
    {
      for (AttributeType attr : parent.getOptionalAttributeChain())
      for (ObjectClass parent : parents)
      {
        inheritedAttrs.add(attr.getNameOrOID());
        for (AttributeType attr : parent.getOptionalAttributeChain())
        {
          inheritedAttrs.add(attr.getNameOrOID());
        }
      }
    }
    model = (DefaultListModel)optionalAttributes.getModel();
@@ -422,6 +436,41 @@
    }
  }
  private String getSuperiorText(ObjectClass oc)
  {
    String n;
    Set<ObjectClass> superiors = oc.getSuperiorClasses();
    if (superiors == null)
    {
      n = null;
    }
    else
    {
      if (superiors.isEmpty())
      {
        n = NOT_APPLICABLE.toString();
      }
      else if (superiors.size() == 1)
      {
        n = superiors.iterator().next().getPrimaryName();
      }
      else
      {
        SortedSet<String> names = new TreeSet<String>();
        for (ObjectClass superior : superiors)
        {
          names.add(superior.getPrimaryName());
        }
        n = Utilities.getStringFromCollection(names, ", ");
      }
    }
    if (n == null)
    {
      n = NOT_APPLICABLE.toString();
    }
    return n;
  }
  /**
   * Returns the message describing the object class type (structural, obsolete,
   * etc.) of a given object class.
opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
@@ -99,6 +99,8 @@
import org.opends.messages.MessageBuilder;
import org.opends.messages.MessageDescriptor;
import org.opends.quicksetup.ui.CustomHTMLEditorKit;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.ObjectClassType;
import org.opends.server.types.OpenDsException;
import org.opends.server.util.ServerConstants;
@@ -1428,14 +1430,15 @@
   * @param newElements the new items for the combo box model.
   * @param model the combo box model to be updated.
   */
  protected void updateComboBoxModel(final Collection<?> newElements,
      final DefaultComboBoxModel model)
  protected void updateComboBoxModel(Collection<?> newElements,
      DefaultComboBoxModel model)
  {
    updateComboBoxModel(newElements, model, null);
  }
  /**
   * Updates a combo box model with a number of items.
   * The method assumes that is called outside the event thread.
   * @param newElements the new items for the combo box model.
   * @param model the combo box model to be updated.
   * @param comparator the object that will be used to compare the objects in
@@ -1449,70 +1452,7 @@
    {
      public void run()
      {
        boolean changed = newElements.size() != model.getSize();
        if (!changed)
        {
          int i = 0;
          for (Object newElement : newElements)
          {
            if (comparator == null)
            {
              changed = !newElement.equals(model.getElementAt(i));
            }
            else
            {
              changed =
                comparator.compare(newElement, model.getElementAt(i)) != 0;
            }
            if (changed)
            {
              break;
            }
            i++;
          }
        }
        if (changed)
        {
          Object selected = model.getSelectedItem();
          model.removeAllElements();
          boolean selectDefault = false;
          for (Object newElement : newElements)
          {
            model.addElement(newElement);
          }
          if (selected != null)
          {
            if (model.getIndexOf(selected) != -1)
            {
              model.setSelectedItem(selected);
            }
            else
            {
              selectDefault = true;
            }
          }
          else
          {
            selectDefault = true;
          }
          if (selectDefault)
          {
            for (int i=0; i<model.getSize(); i++)
            {
              Object o = model.getElementAt(i);
              if (o instanceof CategorizedComboBoxElement)
              {
                if (((CategorizedComboBoxElement)o).getType() ==
                  CategorizedComboBoxElement.Type.CATEGORY)
                {
                  continue;
                }
              }
              model.setSelectedItem(o);
              break;
            }
          }
        }
        Utilities.updateComboBoxModel(newElements, model, comparator);
      }
    });
  }
@@ -2140,10 +2080,17 @@
        getInfo().getDirContext().search(Utilities.getJNDIName(dn),
            filter, ctls);
      while (result.hasMore())
      try
      {
        SearchResult sr = result.next();
        entryExists = sr != null;
        while (result.hasMore())
        {
          SearchResult sr = result.next();
          entryExists = sr != null;
        }
      }
      finally
      {
        result.close();
      }
    }
    catch (Throwable t)
@@ -2175,23 +2122,30 @@
        getInfo().getDirContext().search(Utilities.getJNDIName(dn),
            filter, ctls);
      while (result.hasMore())
      try
      {
        SearchResult sr = result.next();
        Set<String> values = ConnectionUtils.getValues(sr,
            ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
        if (values != null)
        while (result.hasMore())
        {
          for (String s : values)
          SearchResult sr = result.next();
          Set<String> values = ConnectionUtils.getValues(sr,
              ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
          if (values != null)
          {
            if (s.equalsIgnoreCase(objectClass))
            for (String s : values)
            {
              hasObjectClass = true;
              break;
              if (s.equalsIgnoreCase(objectClass))
              {
                hasObjectClass = true;
                break;
              }
            }
          }
        }
      }
      finally
      {
        result.close();
      }
    }
    catch (Throwable t)
    {
@@ -2321,4 +2275,52 @@
  {
    return taskDateFormat.format(date);
  }
  /**
   * Checks whether the provided superior object classes are compatible with
   * the provided object class type.  If not, the method updates the provided
   * list of error messages with a message describing the incompatibility.
   * @param objectClassSuperiors the superior object classes.
   * @param objectClassType the object class type.
   * @param errors the list of error messages.
   */
  protected void checkCompatibleSuperiors(Set<ObjectClass> objectClassSuperiors,
      ObjectClassType objectClassType, List<Message> errors)
  {
    SortedSet<String> notCompatibleClasses =
      new TreeSet<String>(new LowerCaseComparator());
    for (ObjectClass oc : objectClassSuperiors)
    {
      if (oc.getObjectClassType() == ObjectClassType.ABSTRACT)
      {
        // Nothing to do.
      }
      else if (oc.getObjectClassType() != objectClassType)
      {
        notCompatibleClasses.add(oc.getNameOrOID());
      }
    }
    if (!notCompatibleClasses.isEmpty())
    {
      String arg = Utilities.getStringFromCollection(notCompatibleClasses,
          ", ");
      if (objectClassType == ObjectClassType.STRUCTURAL)
      {
        errors.add(
            ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_STRUCTURAL.get(arg));
      }
      else if (objectClassType == ObjectClassType.AUXILIARY)
      {
        errors.add(
            ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_AUXILIARY.get(arg));
      }
      else if (objectClassType == ObjectClassType.ABSTRACT)
      {
        errors.add(
            ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_ABSTRACT.get(arg));
      }
    }
  }
}
opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java
@@ -727,7 +727,7 @@
   * @return <CODE>true</CODE> if the user chose to close the dialog discarding
   * the provided input and <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled()
  public boolean isCanceled()
  {
    return schedule == null;
  }
opends/src/guitools/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java
@@ -455,12 +455,11 @@
            schema.getObjectClass(ocValue.getStructural().toLowerCase());
          if (oc != null)
          {
            ObjectClass parent = oc.getSuperiorClass();
            while (parent != null)
            Set<String> names = getObjectClassSuperiorValues(oc);
            for (String name : names)
            {
              sb.append("\n");
              sb.append(attrName+": "+parent.getNameOrOID());
              parent = parent.getSuperiorClass();
              sb.append(attrName+": "+name);
            }
          }
        }
@@ -713,4 +712,27 @@
    }
    return filteredValue;
  }
  /**
   * Returns the list of superior object classes (to top) for a given object
   * class.
   * @param oc the object class.
   * @return the set of superior object classes for a given object classes.
   */
  protected Set<String> getObjectClassSuperiorValues(
      ObjectClass oc)
  {
    Set<String> names = new LinkedHashSet<String>();
    Set<ObjectClass> parents = oc.getSuperiorClasses();
    if (parents != null && !parents.isEmpty())
    {
      for (ObjectClass parent : parents)
      {
        names.add(parent.getNameOrOID());
        names.addAll(getObjectClassSuperiorValues(parent));
      }
    }
    return names;
  }
}
opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui.components;
@@ -174,7 +174,7 @@
      scheduleDlg.setModal(true);
    }
    scheduleDlg.setVisible(true);
    if (!schedulePanel.isCancelled())
    if (!schedulePanel.isCanceled())
    {
      setSchedule(schedulePanel.getSchedule());
    }
opends/src/guitools/org/opends/guitools/controlpanel/ui/components/SuperiorObjectClassesEditor.java
New file
@@ -0,0 +1,392 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui.components;
import static org.opends.messages.AdminToolMessages.*;
import java.awt.CardLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.Box;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.opends.guitools.controlpanel.event.SuperiorObjectClassesChangedEvent;
import org.opends.guitools.controlpanel.event.
 SuperiorObjectClassesChangedListener;
import org.opends.guitools.controlpanel.ui.GenericDialog;
import org.opends.guitools.controlpanel.ui.SelectObjectClassesPanel;
import org.opends.guitools.controlpanel.ui.renderer.
 SchemaElementComboBoxCellRenderer;
import org.opends.guitools.controlpanel.util.LowerCaseComparator;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Schema;
/**
 * A panel that can be used to select one (or several) object classes.
 */
public class SuperiorObjectClassesEditor extends JPanel
{
  private static final long serialVersionUID = 123123973933568L;
  private Set<ObjectClass> toExclude = new HashSet<ObjectClass>();
  private JComboBox singleSuperior = Utilities.createComboBox();
  private JLabel multipleSuperiors = Utilities.createDefaultLabel();
  private JButton bSpecifyMultiple = Utilities.createButton(
      INFO_CTRL_PANEL_SPECIFY_MULTIPLE_SUPERIORS_LABEL.get());
  private JButton bUpdateMultiple = Utilities.createButton(
      INFO_CTRL_PANEL_UPDATE_MULTIPLE_SUPERIORS_LABEL.get());
  private SelectObjectClassesPanel superiorsPanel;
  private GenericDialog superiorsDialog;
  private String MULTIPLE = "Multiple";
  private String SINGLE = "Single";
  private CardLayout cardLayout = new CardLayout();
  private boolean isMultiple;
  private Set<ObjectClass> selectedMultipleSuperiors =
    new HashSet<ObjectClass>();
  private Set<SuperiorObjectClassesChangedListener> listeners =
    new HashSet<SuperiorObjectClassesChangedListener>();
  private Schema schema;
  /**
   * Default constructor for this panel.
   */
  public SuperiorObjectClassesEditor()
  {
    super(new CardLayout());
    cardLayout = (CardLayout)getLayout();
    setOpaque(false);
    createLayout();
  }
  /**
   * Constructor for this panel.
   * @param schema a non {@code null} schema object.
   */
  public SuperiorObjectClassesEditor(Schema schema)
  {
    this();
    updateWithSchema(schema);
  }
  /**
   * Creates the layout of this panel.
   */
  private void createLayout()
  {
    bSpecifyMultiple.setToolTipText(
        INFO_CTRL_PANEL_SPECIFY_MULTIPLE_SUPERIORS_TOOLTIP.get().toString());
    bSpecifyMultiple.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ev)
      {
        specifyMultipleClicked();
      }
    });
    bUpdateMultiple.setToolTipText(
        INFO_CTRL_PANEL_UPDATE_MULTIPLE_SUPERIORS_TOOLTIP.get().toString());
    bUpdateMultiple.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ev)
      {
        updateMultipleClicked();
      }
    });
    SchemaElementComboBoxCellRenderer renderer = new
    SchemaElementComboBoxCellRenderer(singleSuperior);
    DefaultComboBoxModel model = new DefaultComboBoxModel();
    singleSuperior.setModel(model);
    singleSuperior.setRenderer(renderer);
    ItemListener itemListener = new ItemListener()
    {
      /**
       * {@inheritDoc}
       */
      public void itemStateChanged(ItemEvent ev)
      {
        notifyListeners();
      }
    };
    singleSuperior.addItemListener(itemListener);
    JPanel singlePanel = new JPanel(new GridBagLayout());
    singlePanel.setOpaque(false);
    JPanel multiplePanel = new JPanel(new GridBagLayout());
    multiplePanel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.anchor = GridBagConstraints.WEST;
    singlePanel.add(singleSuperior, gbc);
    multiplePanel.add(multipleSuperiors, gbc);
    gbc.gridx ++;
    gbc.insets.left = 5;
    gbc.weightx = 0.0;
    gbc.fill = GridBagConstraints.NONE;
    singlePanel.add(bSpecifyMultiple, gbc);
    multiplePanel.add(bUpdateMultiple, gbc);
    gbc.gridx ++;
    gbc.insets.left = 0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 0.1;
    singlePanel.add(Box.createHorizontalGlue(), gbc);
    multiplePanel.add(Box.createHorizontalGlue(), gbc);
    add(singlePanel, SINGLE);
    add(multiplePanel, MULTIPLE);
    Set<ObjectClass> empty = Collections.emptySet();
    setSelectedSuperiors(empty);
  }
  /**
   * Sets the list of object classes that this panel should not display
   * (mainly used to not display the object class for which we are editing
   * the superior object classes).
   * @param toExclude the list of object classes to exclude.
   */
  public void setObjectClassesToExclude(Set<ObjectClass> toExclude)
  {
    this.toExclude.clear();
    this.toExclude.addAll(toExclude);
    updateWithSchema(schema);
    if (superiorsPanel != null)
    {
      superiorsPanel.setObjectClassesToExclude(toExclude);
    }
  }
  /**
   * Returns the list of object classes that this panel will not display.
   * @return the list of object classes that this panel will not display.
   */
  public Set<ObjectClass> getObjectClassToExclude()
  {
    return Collections.unmodifiableSet(toExclude);
  }
  /**
   * Sets the list of superior object classes that must be displayed by
   * this panel.
   * @param objectClasses the list of superior object classes to be displayed.
   */
  public void setSelectedSuperiors(Set<ObjectClass> objectClasses)
  {
    isMultiple = objectClasses.size() > 1;
    if (isMultiple)
    {
      cardLayout.show(this, MULTIPLE);
      selectedMultipleSuperiors.clear();
      selectedMultipleSuperiors.addAll(objectClasses);
      updateMultipleSuperiorsLabel(selectedMultipleSuperiors);
    }
    else
    {
      if (objectClasses.size() == 1)
      {
        singleSuperior.setSelectedItem(objectClasses.iterator().next());
      }
      cardLayout.show(this, SINGLE);
    }
  }
  private void updateMultipleSuperiorsLabel(
      Set<ObjectClass> superiors)
  {
    SortedSet<String> orderedOcs =
      new TreeSet<String>(new LowerCaseComparator());
    for (ObjectClass oc : superiors)
    {
      orderedOcs.add(oc.getNameOrOID());
    }
    String s = Utilities.getStringFromCollection(orderedOcs, ", ");
    multipleSuperiors.setText(s);
  }
  /**
   * Returns the list of superior object classes displayed by this panel.
   * @return the list of superior object classes displayed by this panel.
   */
  public Set<ObjectClass> getSelectedSuperiors()
  {
    if (isMultiple)
    {
      return Collections.unmodifiableSet(selectedMultipleSuperiors);
    }
    else
    {
      ObjectClass oc = (ObjectClass)singleSuperior.getSelectedItem();
      if (oc == null)
      {
        return Collections.emptySet();
      }
      else
      {
        return Collections.singleton(
            (ObjectClass)(singleSuperior.getSelectedItem()));
      }
    }
  }
  /**
   * Sets the schema to be used by this panel.  This method assumes that it
   * is being called from the event thread.
   * @param schema the schema to be used by this panel.
   */
  public void setSchema(Schema schema)
  {
    updateWithSchema(schema);
    if (superiorsPanel != null)
    {
      superiorsPanel.setSchema(schema);
    }
  }
  private void updateWithSchema(Schema schema)
  {
    HashMap<String, ObjectClass> objectClassNameMap = new HashMap<String,
    ObjectClass>();
    for (String key : schema.getObjectClasses().keySet())
    {
      ObjectClass oc = schema.getObjectClass(key);
      if (!toExclude.contains(oc))
      {
        objectClassNameMap.put(oc.getNameOrOID(), oc);
      }
    }
    SortedSet<String> orderedKeys =
      new TreeSet<String>(new LowerCaseComparator());
    orderedKeys.addAll(objectClassNameMap.keySet());
    ArrayList<Object> newParents = new ArrayList<Object>();
    for (String key : orderedKeys)
    {
      newParents.add(objectClassNameMap.get(key));
    }
    Utilities.updateComboBoxModel(newParents,
        (DefaultComboBoxModel)singleSuperior.getModel());
    if (this.schema == null)
    {
      // Select the values.
      ObjectClass topClass = schema.getObjectClass("top");
      singleSuperior.setSelectedItem(topClass);
    }
    this.schema = schema;
  }
  /**
   * Adds a listener that will receive events when a change is made in the
   * displayed superior object classes.
   * @param listener the listener to be added.
   */
  public void addParentObjectClassesChangedListener(
      SuperiorObjectClassesChangedListener listener)
  {
    listeners.add(listener);
  }
  /**
   * Removes the provided listener.
   * @param listener the listener to be removed.
   */
  public void removeParentObjectClassesChangedListener(
      SuperiorObjectClassesChangedListener listener)
  {
    listeners.remove(listener);
  }
  private void specifyMultipleClicked()
  {
    updateMultipleClicked();
  }
  private void updateMultipleClicked()
  {
     Set<ObjectClass> selectedObjectClasses = getSelectedSuperiors();
     // Display the panel with all the stuff.
     if (superiorsPanel == null)
     {
       superiorsPanel = new SelectObjectClassesPanel();
       superiorsPanel.setSchema(schema);
       if (!toExclude.isEmpty())
       {
         superiorsPanel.setObjectClassesToExclude(toExclude);
       }
       superiorsDialog = new GenericDialog(Utilities.getFrame(this),
           superiorsPanel);
       Utilities.centerGoldenMean(superiorsDialog,
           Utilities.getParentDialog(this));
       superiorsDialog.setModal(true);
       superiorsDialog.pack();
     }
     superiorsPanel.setSelectedObjectClasses(selectedObjectClasses);
     superiorsDialog.setVisible(true);
     if (!superiorsPanel.isCanceled())
     {
       setSelectedSuperiors(superiorsPanel.getSelectedObjectClasses());
       notifyListeners();
     }
  }
  private void notifyListeners()
  {
    SuperiorObjectClassesChangedEvent ev =
      new SuperiorObjectClassesChangedEvent(this, getSelectedSuperiors());
    for (SuperiorObjectClassesChangedListener listener : listeners)
    {
      listener.parentObjectClassesChanged(ev);
    }
  }
}
opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/SchemaElementComboBoxCellRenderer.java
@@ -56,6 +56,15 @@
  }
  /**
   * Constructor of the cell renderer.
   * @param list the list containing the elements to be rendered.
   */
  public SchemaElementComboBoxCellRenderer(JList list)
  {
    super(list);
  }
  /**
   * {@inheritDoc}
   */
  public Component getListCellRendererComponent(JList list, Object value,
opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
@@ -47,6 +47,7 @@
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -59,6 +60,7 @@
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapName;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
@@ -90,6 +92,7 @@
import org.opends.guitools.controlpanel.ControlPanel;
import org.opends.guitools.controlpanel.browser.IconPool;
import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement;
import org.opends.guitools.controlpanel.datamodel.ConfigReadException;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
@@ -2753,4 +2756,94 @@
  {
    comp.addMouseListener(new ClickTooltipDisplayer());
  }
  /**
   * Updates a combo box model with a number of items.
   * The method assumes that is being called from the event thread.
   * @param newElements the new items for the combo box model.
   * @param model the combo box model to be updated.
   */
  public static void updateComboBoxModel(Collection<?> newElements,
      DefaultComboBoxModel model)
  {
    updateComboBoxModel(newElements, model, null);
  }
  /**
   * Updates a combo box model with a number of items.
   * The method assumes that is being called from the event thread.
   * @param newElements the new items for the combo box model.
   * @param model the combo box model to be updated.
   * @param comparator the object that will be used to compare the objects in
   * the model.  If <CODE>null</CODE>, the equals method will be used.
   */
  public static void updateComboBoxModel(Collection<?> newElements,
      DefaultComboBoxModel model,
      Comparator<Object> comparator)
  {
    boolean changed = newElements.size() != model.getSize();
    if (!changed)
    {
      int i = 0;
      for (Object newElement : newElements)
      {
        if (comparator == null)
        {
          changed = !newElement.equals(model.getElementAt(i));
        }
        else
        {
          changed =
            comparator.compare(newElement, model.getElementAt(i)) != 0;
        }
        if (changed)
        {
          break;
        }
        i++;
      }
    }
    if (changed)
    {
      Object selected = model.getSelectedItem();
      model.removeAllElements();
      boolean selectDefault = false;
      for (Object newElement : newElements)
      {
        model.addElement(newElement);
      }
      if (selected != null)
      {
        if (model.getIndexOf(selected) != -1)
        {
          model.setSelectedItem(selected);
        }
        else
        {
          selectDefault = true;
        }
      }
      else
      {
        selectDefault = true;
      }
      if (selectDefault)
      {
        for (int i=0; i<model.getSize(); i++)
        {
          Object o = model.getElementAt(i);
          if (o instanceof CategorizedComboBoxElement)
          {
            if (((CategorizedComboBoxElement)o).getType() ==
              CategorizedComboBoxElement.Type.CATEGORY)
            {
              continue;
            }
          }
          model.setSelectedItem(o);
          break;
        }
      }
    }
  }
}
opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
@@ -139,7 +139,7 @@
      boolean isInteractive;
      boolean isQuiet;
      boolean isVerbose;
      boolean isCancelled = false;
      boolean isCanceled = false;
      /* Step 1: analyze the arguments.
       */
@@ -222,7 +222,7 @@
        }
        else
        {
          isCancelled = askWhatToDelete(userData, outsideDbs, outsideLogs);
          isCanceled = askWhatToDelete(userData, outsideDbs, outsideLogs);
        }
      }
      String adminUid = args.getAdministratorUID();
@@ -275,12 +275,12 @@
       * Step 4: check if server is running.  Depending if it is running and the
       * OS we are running, ask for authentication information.
       */
      if (!isCancelled)
      if (!isCanceled)
      {
        isCancelled = checkServerState(userData);
        isCanceled = checkServerState(userData);
      }
      if (isCancelled && !userData.isForceOnError())
      if (isCanceled && !userData.isForceOnError())
      {
        LOG.log(Level.INFO, "User cancelled uninstall.");
        userData = null;
opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
@@ -1599,7 +1599,7 @@
    Utilities.centerOnComponent(loginDialog, qs.getDialog().getFrame());
    loginDialog.setModal(true);
    loginDialog.setVisible(true);
    if (!loginDialog.isCancelled())
    if (!loginDialog.isCanceled())
    {
      getUninstallUserData().setAdminUID(loginDialog.getAdministratorUid());
      getUninstallUserData().setAdminPwd(loginDialog.getAdministratorPwd());
opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java
@@ -96,7 +96,7 @@
  private JButton cancelButton;
  private JButton okButton;
  private boolean isCancelled = true;
  private boolean isCanceled = true;
  private ApplicationTrustManager trustManager;
  private int timeout;
@@ -144,9 +144,9 @@
   * @return <CODE>true</CODE> if the user clicked on cancel and
   * <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled()
  public boolean isCanceled()
  {
    return isCancelled;
    return isCanceled;
  }
  /**
@@ -372,7 +372,7 @@
   */
  private void cancelClicked()
  {
    isCancelled = true;
    isCanceled = true;
    dispose();
  }
@@ -588,7 +588,7 @@
          UIFactory.setTextStyle(lPwd,
              UIFactory.TextStyle.PRIMARY_FIELD_VALID);
          isCancelled = false;
          isCanceled = false;
          cancelButton.setEnabled(true);
          okButton.setEnabled(true);
          dispose();
opends/src/messages/messages/admin_tool.properties
@@ -2343,6 +2343,7 @@
INFO_CTRL_PANEL_CREATING_OBJECTCLASS_PROGRESS=Creating object class '%s'
INFO_CTRL_PANEL_OBJECTCLASS_NAME_LABEL=Name:
INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL=Superior:
INFO_CTRL_PANEL_OBJECTCLASS_PARENTS_LABEL=Superiors:
INFO_CTRL_PANEL_OBJECTCLASS_OID_LABEL=OID:
INFO_CTRL_PANEL_OBJECTCLASS_ALIASES_LABEL=Aliases:
INFO_CTRL_PANEL_OBJECTCLASS_ORIGIN_LABEL=Origin:
@@ -2351,6 +2352,34 @@
INFO_CTRL_PANEL_OBJECTCLASS_TYPE_LABEL=Type:
INFO_CTRL_PANEL_OBJECTCLASS_ATTRIBUTES_LABEL=Attributes:
INFO_CTRL_PANEL_SPECIFY_MULTIPLE_SUPERIORS_LABEL=Multiple Superiors...
INFO_CTRL_PANEL_UPDATE_MULTIPLE_SUPERIORS_LABEL=Change...
INFO_CTRL_PANEL_SPECIFY_MULTIPLE_SUPERIORS_TOOLTIP=Click on this button to \
 specify multiple superiors for this object class.
INFO_CTRL_PANEL_UPDATE_MULTIPLE_SUPERIORS_TOOLTIP=Click on this button to \
 specify the superiors of this object class.
INFO_CTRL_PANEL_SUPERIOR_OBJECTCLASSES_TITLE=Superior Object Classes
INFO_CTRL_PANEL_ERROR_NO_SUPERIOR_SELECTED=You must select at least one \
 superior object class.
INFO_CTRL_PANEL_SUPERIOR_OBJECTCLASSES_INSTRUCTIONS=Specify the superior \
 object classes.
INFO_CTRL_PANEL_ADDREMOVE_AVAILABLE_OBJECTCLASSES=Available Object Classes:
INFO_CTRL_PANEL_ADDREMOVE_SELECTED_OBJECTCLASSES=Selected Object Classes:
SEVERE_ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_STRUCTURAL=You are editing \
 a structural object class.  The following object classes are auxiliary: %s.%n\
 Only structural or abstract object classes can be used as superior object \
 classes of a structural object class.
SEVERE_ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_AUXILIARY=You are editing \
 an auxiliary object class.  The following object classes are structural: %s.%n\
 Only auxiliary or abstract object classes can be used as superior object \
 classes of an auxiliary object class.
SEVERE_ERR_CTRL_PANEL_INCOMPATIBLE_SUPERIORS_WITH_ABSTRACT=You are editing \
 an abstract object class.  The following object classes are structural or \
 auxiliary: %s.%nOnly auxiliary object classes can be used as superior object \
 classes of an abstract object class.
INFO_CTRL_PANEL_NEW_OU_NAME_LABEL=Name:
INFO_CTRL_PANEL_NEW_OU_DESCRIPTION_LABEL=Description:
INFO_CTRL_PANEL_NEW_OU_ENTRY_DN_LABEL=Entry DN:
opends/src/quicksetup/org/opends/quicksetup/installer/ui/JavaArgumentsDialog.java
@@ -80,7 +80,7 @@
  private JButton cancelButton;
  private JButton okButton;
  private boolean isCancelled = true;
  private boolean isCanceled = true;
  private Message message;
@@ -155,9 +155,9 @@
   * @return <CODE>true</CODE> if the user clicked on cancel and
   * <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled()
  public boolean isCanceled()
  {
    return isCancelled;
    return isCanceled;
  }
  /**
@@ -453,7 +453,7 @@
   */
  private void cancelClicked()
  {
    isCancelled = true;
    isCanceled = true;
    dispose();
  }
@@ -593,7 +593,7 @@
          {
            if (displayWebStartWarningIfRequired())
            {
              isCancelled = false;
              isCanceled = false;
              dispose();
            }
          }
opends/src/quicksetup/org/opends/quicksetup/installer/ui/RuntimeOptionsPanel.java
@@ -308,7 +308,7 @@
    dlg.pack();
    dlg.setModal(true);
    dlg.setVisible(true);
    if (!dlg.isCancelled())
    if (!dlg.isCanceled())
    {
      serverJavaArgs = dlg.getJavaArguments();
      lServer.setText(JavaArguments.getMessageForJLabel(
@@ -326,7 +326,7 @@
    dlg.pack();
    dlg.setModal(true);
    dlg.setVisible(true);
    if (!dlg.isCancelled())
    if (!dlg.isCanceled())
    {
      importJavaArgs = dlg.getJavaArguments();
      lImport.setText(JavaArguments.getMessageForJLabel(
opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java
@@ -95,7 +95,7 @@
  private SelectAliasDialog aliasDlg;
  private boolean isCancelled = true;
  private boolean isCanceled = true;
  private SecurityOptions securityOptions;
@@ -147,9 +147,9 @@
   * @return <CODE>true</CODE> if the user clicked on cancel and
   * <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled()
  public boolean isCanceled()
  {
    return isCancelled;
    return isCanceled;
  }
  /**
@@ -174,7 +174,7 @@
    securityOptions = options;
    updateContents();
    isCancelled = true;
    isCanceled = true;
    setVisible(true);
  }
@@ -653,7 +653,7 @@
   */
  private void cancelClicked()
  {
    isCancelled = true;
    isCanceled = true;
    dispose();
  }
@@ -710,7 +710,7 @@
              if (!certificateHasAlias)
              {
                selectedAlias = null;
                isCancelled = false;
                isCanceled = false;
                dispose();
              }
              else if (aliases.length > 1)
@@ -721,23 +721,23 @@
                }
                aliasDlg.display(aliases);
                if (!aliasDlg.isCancelled())
                if (!aliasDlg.isCanceled())
                {
                  selectedAlias = aliasDlg.getSelectedAlias();
                  isCancelled = false;
                  isCanceled = false;
                  dispose();
                }
              }
              else
              {
                selectedAlias = aliases[0];
                isCancelled = false;
                isCanceled = false;
                dispose();
              }
            }
            else
            {
              isCancelled = false;
              isCanceled = false;
              dispose();
            }
          }
opends/src/quicksetup/org/opends/quicksetup/installer/ui/SelectAliasDialog.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.installer.ui;
@@ -58,7 +58,7 @@
{
  private JButton okButton;
  private JComboBox comboAliases;
  private boolean isCancelled;
  private boolean isCanceled;
  private static final long serialVersionUID = -8140704273612764046L;
@@ -103,7 +103,7 @@
      throw new IllegalArgumentException(
          "The provided aliases are null or empty.");
    }
    isCancelled = true;
    isCanceled = true;
    TreeSet<String> s = new TreeSet<String>();
    for (int i=0; i<aliases.length; i++)
    {
@@ -122,9 +122,9 @@
   * @return <CODE>true</CODE> if the user clicked on cancel and
   * <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled()
  public boolean isCanceled()
  {
    return isCancelled;
    return isCanceled;
  }
  /**
@@ -231,7 +231,7 @@
   */
  private void cancelClicked()
  {
    isCancelled = true;
    isCanceled = true;
    dispose();
  }
@@ -241,7 +241,7 @@
   */
  private void okClicked()
  {
    isCancelled = false;
    isCanceled = false;
    dispose();
  }
opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.installer.ui;
@@ -594,7 +594,7 @@
        public void actionPerformed(ActionEvent ev)
        {
          getConfigureSecureAccessDialog().display(securityOptions);
          if (!getConfigureSecureAccessDialog().isCancelled())
          if (!getConfigureSecureAccessDialog().isCanceled())
          {
            securityOptions =
              getConfigureSecureAccessDialog().getSecurityOptions();
opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends;
@@ -2020,8 +2020,7 @@
    // Make sure that the new objectclass doesn't reference an undefined
    // superior class, or an undefined required or optional attribute type,
    // and that none of them are OBSOLETE.
    ObjectClass superiorClass = objectClass.getSuperiorClass();
    if (superiorClass != null)
    for(ObjectClass superiorClass : objectClass.getSuperiorClasses())
    {
      if (! schema.hasObjectClass(superiorClass.getOID()))
      {
@@ -2213,12 +2212,15 @@
    // other objectclass.
    for (ObjectClass oc : schema.getObjectClasses().values())
    {
      ObjectClass superiorClass = oc.getSuperiorClass();
      if ((superiorClass != null) && superiorClass.equals(removeClass))
      for(ObjectClass superiorClass : oc.getSuperiorClasses())
      {
        Message message = ERR_SCHEMA_MODIFY_REMOVE_OC_SUPERIOR_CLASS.get(
            removeClass.getNameOrOID(), superiorClass.getNameOrOID());
        throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
        if (superiorClass.equals(removeClass))
        {
          Message message = ERR_SCHEMA_MODIFY_REMOVE_OC_SUPERIOR_CLASS.get(
              removeClass.getNameOrOID(), superiorClass.getNameOrOID());
          throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
                  message);
        }
      }
    }
@@ -3755,15 +3757,15 @@
      return;
    }
    ObjectClass superiorClass = objectClass.getSuperiorClass();
    if ((superiorClass != null) &&
        schemaFile.equals(superiorClass.getSchemaFile()) &&
        (! addedClasses.contains(superiorClass)))
    for(ObjectClass superiorClass : objectClass.getSuperiorClasses())
    {
      addObjectClassToSchemaFile(schema, schemaFile, superiorClass, values,
                                 addedClasses, depth+1);
      if (schemaFile.equals(superiorClass.getSchemaFile()) &&
          (! addedClasses.contains(superiorClass)))
      {
        addObjectClassToSchemaFile(schema, schemaFile, superiorClass, values,
                                   addedClasses, depth+1);
      }
    }
    values.add(AttributeValues.create(objectClassesType,
                                  objectClass.getDefinition()));
    addedClasses.add(objectClass);
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -3803,7 +3803,8 @@
      objectClass = new ObjectClass(definition, name,
                                    Collections.singleton(name), oid, null,
                                    getTopObjectClass(), null, null,
                                    Collections.singleton(getTopObjectClass()),
                                    null, null,
                                    ObjectClassType.STRUCTURAL, false, null);
    }
@@ -3834,7 +3835,8 @@
      objectClass = new ObjectClass(definition, name,
                                    Collections.singleton(name), oid, null,
                                    getTopObjectClass(), null, null,
                                    Collections.singleton(getTopObjectClass()),
                                    null, null,
                                    ObjectClassType.AUXILIARY, false, null);
    }
opends/src/server/org/opends/server/schema/ObjectClassSyntax.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.schema;
import org.opends.messages.Message;
@@ -421,11 +421,11 @@
    List<String> names = new LinkedList<String>();
    String description = null;
    boolean isObsolete = false;
    ObjectClass superiorClass = DirectoryServer.getTopObjectClass();
    Set<AttributeType> requiredAttributes = new LinkedHashSet<AttributeType>();
    Set<AttributeType> optionalAttributes = new LinkedHashSet<AttributeType>();
    ObjectClassType objectClassType = superiorClass
        .getObjectClassType();
    Set<ObjectClass> superiorClasses = new LinkedHashSet<ObjectClass>();
    //Default OC Type is STRUCTURAL ( RFC 4512 4.1.1)
    ObjectClassType objectClassType = ObjectClassType.STRUCTURAL;
    Map<String, List<String>> extraProperties =
      new LinkedHashMap<String, List<String>>();
@@ -604,10 +604,9 @@
        // by one or more names separated by spaces  and the dollar sign
        //  character, followed by a closing parenthesis.
        c = valueStr.charAt(pos++);
        LinkedList<ObjectClass> listSupOCs = new LinkedList<ObjectClass>();
        if(c == '(')
        {
          LinkedList<ObjectClass> listSupOCs = new LinkedList<ObjectClass>();
          while(true)
          {
            StringBuilder woidBuffer = new StringBuilder();
@@ -633,21 +632,7 @@
              }
            }
            //We don't currently support multiple inheritance of objectclasses.
            //Check to see if we already have a value in the list and make a
            //decision.
            if(listSupOCs.size() > 0 )
            {
              Message message =
                      ERR_ATTR_SYNTAX_OBJECTCLASS_MULTIPLE_SUPERIOR_CLASS.
                      get(oidStr,oid,listSupOCs.get(0).getNameOrOID());
              throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                      message);
            }
            else
            {
              listSupOCs.add(supOC);
            }
            listSupOCs.add(supOC);
            // The next character must be either a dollar sign or a closing
            // parenthesis.
            c = valueStr.charAt(pos++);
@@ -664,13 +649,13 @@
                                           message);
            }
          }
          superiorClass = listSupOCs.get(0);
        }
        else
        {
          StringBuilder woidBuffer = new StringBuilder();
          pos = readWOID(lowerStr, woidBuffer, (pos-1));
          superiorClass = schema.getObjectClass(woidBuffer.toString());
          ObjectClass superiorClass =
                  schema.getObjectClass(woidBuffer.toString());
          if (superiorClass == null)
          {
            if (allowUnknownElements)
@@ -689,23 +674,9 @@
                                           message);
            }
          }
          listSupOCs.add(superiorClass);
        }
        // Use the objectclass type of the superior objectclass to override the
        // objectclass type for the new one.  This could potentially cause a
        // problem if the components in the objectclass description are provided
        // out-of-order, but even if that happens then it doesn't really matter
        // since the objectclass type currently isn't used for anything anyway.
        //If the superior oc is top, set the type to STRUCTURAL.
        if(superiorClass.hasName("top"))
        {
          objectClassType = ObjectClassType.STRUCTURAL;
        }
        else
        {
          objectClassType = superiorClass.getObjectClassType();
        }
        superiorClasses.addAll(listSupOCs);
      }
      else if (lowerTokenName.equals("abstract"))
      {
@@ -910,78 +881,81 @@
      }
    }
    if (superiorClass.getOID().equals(oid))
    //If SUP is not specified, use TOP.
    ObjectClass top = DirectoryServer.getTopObjectClass();
    if(superiorClasses.isEmpty() && !top.getOID().equals(oid))
    {
      // This should only happen for the "top" objectclass.
      superiorClass = null;
      superiorClasses.add(top);
    }
    else
    {
      // Make sure that the inheritance configuration is acceptable.
      ObjectClassType superiorType = superiorClass.getObjectClassType();
      switch (objectClassType)
      for(ObjectClass superiorClass : superiorClasses)
      {
        case ABSTRACT:
          // Abstract classes may only inherit from other abstract classes.
          if (superiorType != ObjectClassType.ABSTRACT)
          {
            Message message =
              WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.
        // Make sure that the inheritance configuration is acceptable.
        ObjectClassType superiorType = superiorClass.getObjectClassType();
        switch (objectClassType)
        {
          case ABSTRACT:
            // Abstract classes may only inherit from other abstract classes.
            if (superiorType != ObjectClassType.ABSTRACT)
            {
              Message message =
                WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.
                  get(oid, objectClassType.toString(), superiorType.toString(),
                      superiorClass.getNameOrOID());
            throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                         message);
          }
          break;
                        superiorClass.getNameOrOID());
              throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                           message);
            }
            break;
        case AUXILIARY:
          // Auxiliary classes may only inherit from abstract classes or other
          // auxiliary classes.
          if ((superiorType != ObjectClassType.ABSTRACT) &&
              (superiorType != ObjectClassType.AUXILIARY))
          {
            Message message =
              WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.
          case AUXILIARY:
            // Auxiliary classes may only inherit from abstract classes or other
            // auxiliary classes.
            if ((superiorType != ObjectClassType.ABSTRACT) &&
                (superiorType != ObjectClassType.AUXILIARY))
            {
              Message message =
                WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.
                  get(oid, objectClassType.toString(), superiorType.toString(),
                      superiorClass.getNameOrOID());
            throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                         message);
          }
          break;
                        superiorClass.getNameOrOID());
              throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                           message);
            }
            break;
        case STRUCTURAL:
          // Structural classes may only inherit from abstract classes or other
          // structural classes.
          if ((superiorType != ObjectClassType.ABSTRACT) &&
              (superiorType != ObjectClassType.STRUCTURAL))
          {
            Message message =
              WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.
          case STRUCTURAL:
            // Structural classes may only inherit from abstract classes or
            // other structural classes.
            if ((superiorType != ObjectClassType.ABSTRACT) &&
                (superiorType != ObjectClassType.STRUCTURAL))
            {
              Message message =
                WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.
                  get(oid, objectClassType.toString(), superiorType.toString(),
                      superiorClass.getNameOrOID());
            throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                         message);
          }
                        superiorClass.getNameOrOID());
              throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                           message);
            }
          // Structural classes must have the "top" objectclass somewhere in the
          // superior chain.
          if (! superiorChainIncludesTop(superiorClass))
          {
            Message message =
              WARN_ATTR_SYNTAX_OBJECTCLASS_STRUCTURAL_SUPERIOR_NOT_TOP.
                  get(oid);
            throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                         message);
          }
          break;
            // Structural classes must have the "top" objectclass somewhere in
            // the superior chain.
            if (! superiorChainIncludesTop(superiorClass))
            {
              Message message =
                WARN_ATTR_SYNTAX_OBJECTCLASS_STRUCTURAL_SUPERIOR_NOT_TOP.
                    get(oid);
              throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                                           message);
            }
            break;
        }
      }
    }
    return new ObjectClass(value.toString(), primaryName, names, oid,
                           description, superiorClass, requiredAttributes,
                           description, superiorClasses, requiredAttributes,
                           optionalAttributes, objectClassType, isObsolete,
                           extraProperties);
  }
@@ -1520,8 +1494,15 @@
    }
    else
    {
      return superiorChainIncludesTop(superiorClass.getSuperiorClass());
      for(ObjectClass oc : superiorClass.getSuperiorClasses())
      {
        if(superiorChainIncludesTop(oc))
        {
          return true;
        }
      }
    }
    return false;
  }
opends/src/server/org/opends/server/types/ObjectClass.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.types;
@@ -93,8 +93,8 @@
  // and its superclasses.
  private final Set<AttributeType> requiredAndOptionalChain;
  // The reference to the superior objectclass.
  private final ObjectClass superiorClass;
  // The reference to one or more superior objectclasses.
  private final Set<ObjectClass> superiorClasses;
  // The objectclass type for this objectclass.
  private final ObjectClassType objectClassType;
@@ -132,9 +132,9 @@
   * @param description
   *          The description for this objectclass, or {@code null} if
   *          there is no description.
   * @param superiorClass
   *          The superior class for this objectclass, or {@code null}
   *          if there is no superior object class.
   * @param superiorClasses
   *          The superior classes for this objectclass, or
   *          {@code null} if there is no superior object class.
   * @param requiredAttributes
   *          The set of required attribute types for this
   *          objectclass.
@@ -152,7 +152,8 @@
   */
  public ObjectClass(String definition, String primaryName,
                     Collection<String> names, String oid,
                     String description, ObjectClass superiorClass,
                     String description,
                     Set<ObjectClass> superiorClasses,
                     Set<AttributeType> requiredAttributes,
                     Set<AttributeType> optionalAttributes,
                     ObjectClassType objectClassType,
@@ -165,7 +166,14 @@
    ensureNotNull(definition, oid);
    this.superiorClass = superiorClass;
    // Construct unmodifiable views of the superior classes.
    if (superiorClasses != null) {
      this.superiorClasses =  Collections
          .unmodifiableSet(new LinkedHashSet<ObjectClass>(
              superiorClasses));
    } else {
      this.superiorClasses = Collections.emptySet();
    }
    int schemaFilePos = definition.indexOf(SCHEMA_PROPERTY_FILENAME);
    if (schemaFilePos > 0)
@@ -215,12 +223,15 @@
      this.requiredAttributes = Collections.emptySet();
    }
    if (this.superiorClass == null) {
    if (this.superiorClasses.isEmpty()) {
      this.requiredAttributesChain = this.requiredAttributes;
    } else {
      Set<AttributeType> tmp = new HashSet<AttributeType>(
          this.requiredAttributes);
      tmp.addAll(this.superiorClass.getRequiredAttributeChain());
      for(ObjectClass oc: this.superiorClasses)
      {
        tmp.addAll(oc.getRequiredAttributeChain());
      }
      this.requiredAttributesChain = Collections.unmodifiableSet(tmp);
    }
@@ -233,12 +244,15 @@
      this.optionalAttributes = Collections.emptySet();
    }
    if (this.superiorClass == null) {
    if (this.superiorClasses.isEmpty()) {
      this.optionalAttributesChain = this.optionalAttributes;
    } else {
      Set<AttributeType> tmp = new HashSet<AttributeType>(
          this.optionalAttributes);
      tmp.addAll(this.superiorClass.getOptionalAttributeChain());
      for(ObjectClass oc : this.superiorClasses)
      {
        tmp.addAll(oc.getOptionalAttributeChain());
      }
      this.optionalAttributesChain = Collections.unmodifiableSet(tmp);
    }
@@ -327,15 +341,14 @@
  /**
   * Retrieves the reference to the superior class for this
   * objectclass.
   * Retrieves an unmodifiable view of the set of direct superior
   * classes for this objectclass.
   *
   * @return The reference to the superior class for this objectlass,
   *         or <code>null</code> if there is none.
   * @return An unmodifiable view of the set of  direct superior
   *                classes for this objectlass,
   */
  public ObjectClass getSuperiorClass() {
    return superiorClass;
  public Set<ObjectClass> getSuperiorClasses() {
    return superiorClasses;
  }
@@ -351,12 +364,12 @@
   */
  public boolean isDescendantOf(ObjectClass objectClass) {
    if (superiorClass == null) {
      return false;
    for(ObjectClass oc : superiorClasses) {
      if(oc.equals(objectClass) || oc.isDescendantOf(objectClass)) {
        return true;
      }
    }
    return (superiorClass.equals(objectClass) || superiorClass
        .isDescendantOf(objectClass));
    return false;
  }
@@ -528,9 +541,24 @@
   */
  protected void toStringContent(StringBuilder buffer) {
    if (superiorClass != null) {
    if (!superiorClasses.isEmpty()) {
      buffer.append(" SUP ");
      buffer.append(superiorClass.getNameOrOID());
      Iterator<ObjectClass> iterator = superiorClasses.iterator();
      ObjectClass oc =  iterator.next();
      if(iterator.hasNext()) {
        buffer.append("( ");
        buffer.append(oc.getNameOrOID());
        while(iterator.hasNext()) {
          buffer.append(" $ ");
          buffer.append(iterator.next().getNameOrOID());
        }
        buffer.append(" )");
      } else {
        buffer.append(oc.getNameOrOID());
      }
    }
    if (objectClassType != null) {
@@ -580,4 +608,4 @@
      }
    }
  }
}
  }
opends/src/server/org/opends/server/types/Schema.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.types;
@@ -3223,8 +3223,7 @@
      for (ObjectClass oc : objectClasses.values())
      {
        if ((oc.getSuperiorClass() != null) &&
            oc.getSuperiorClass().equals(c))
        if (oc.getSuperiorClasses().contains(c))
        {
          ObjectClass newOC = oc.recreateFromDefinition();
          deregisterObjectClass(oc);
opends/src/server/org/opends/server/util/StaticUtils.java
@@ -4467,16 +4467,17 @@
      HashSet<ObjectClass> additionalClasses = null;
      for (ObjectClass oc : objectClasses.keySet())
      {
        ObjectClass superiorClass = oc.getSuperiorClass();
        if ((superiorClass != null) &&
            (! objectClasses.containsKey(superiorClass)))
        for(ObjectClass superiorClass : oc.getSuperiorClasses())
        {
          if (additionalClasses == null)
          if (! objectClasses.containsKey(superiorClass))
          {
            additionalClasses = new HashSet<ObjectClass>();
          }
            if (additionalClasses == null)
            {
              additionalClasses = new HashSet<ObjectClass>();
            }
          additionalClasses.add(superiorClass);
            additionalClasses.add(superiorClass);
          }
        }
      }
@@ -4498,11 +4499,12 @@
        objectClasses.put(objectClass, objectClass.getNameOrOID());
      }
      ObjectClass superiorClass = objectClass.getSuperiorClass();
      if ((superiorClass != null) &&
          (! objectClasses.containsKey(superiorClass)))
      for(ObjectClass superiorClass : objectClass.getSuperiorClasses())
      {
        addObjectClassChain(superiorClass, objectClasses);
        if (! objectClasses.containsKey(superiorClass))
        {
          addObjectClassChain(superiorClass, objectClasses);
        }
      }
    }
  }
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.server.workflowelement.localbackend;
@@ -1007,11 +1007,12 @@
        objectClasses.put(objectClass, objectClass.getNameOrOID());
      }
      ObjectClass superiorClass = objectClass.getSuperiorClass();
      if ((superiorClass != null) &&
          (! objectClasses.containsKey(superiorClass)))
      for(ObjectClass superiorClass : objectClass.getSuperiorClasses())
      {
        addObjectClassChain(superiorClass);
        if (!objectClasses.containsKey(superiorClass))
        {
          addObjectClassChain(superiorClass);
        }
      }
    }
  }
opends/src/server/org/opends/server/workflowelement/ndb/NDBAddOperation.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.server.workflowelement.ndb;
@@ -307,16 +307,18 @@
        HashSet<ObjectClass> additionalClasses = null;
        for (ObjectClass oc : objectClasses.keySet())
        {
          ObjectClass superiorClass = oc.getSuperiorClass();
          if ((superiorClass != null) &&
              (! objectClasses.containsKey(superiorClass)))
          for(ObjectClass superiorClass : oc.getSuperiorClasses())
          {
            if (additionalClasses == null)
            if ((superiorClass != null) &&
                (! objectClasses.containsKey(superiorClass)))
            {
              additionalClasses = new HashSet<ObjectClass>();
            }
              if (additionalClasses == null)
              {
                additionalClasses = new HashSet<ObjectClass>();
              }
            additionalClasses.add(superiorClass);
              additionalClasses.add(superiorClass);
            }
          }
        }
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestObjectClass.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.types;
@@ -58,7 +58,7 @@
      SchemaDefinitionBuilder<ObjectClass> {
    // The superior object class from which this object class
    // inherits.
    private ObjectClass superior;
    private Set<ObjectClass> superior;
    // The type of object class.
    private ObjectClassType objectClassType;
@@ -172,7 +172,26 @@
      if (superior != null)
      {
        definition.append(" SUP ");
        definition.append(superior.getNameOrOID());
        Iterator<ObjectClass> iterator = superior.iterator();
        ObjectClass oc =  iterator.next();
        if(iterator.hasNext())
        {
          definition.append("( ");
          definition.append(oc.getNameOrOID());
          while(iterator.hasNext())
          {
            definition.append(" $ ");
            definition.append(iterator.next().getNameOrOID());
          }
          definition.append(" )");
        }
        else
        {
          definition.append(oc.getNameOrOID());
        }
      }
      if (objectClassType != null)
@@ -267,7 +286,8 @@
      return new ObjectClass(definition.toString(), primaryName, names, oid,
                             description, superior, requiredAttributeTypes,
                             description, superior,
                             requiredAttributeTypes,
                             optionalAttributeTypes, objectClassType,
                             isObsolete, extraProperties);
    }
@@ -292,7 +312,7 @@
     * @param superior
     *          The superior.
     */
    public void setSuperior(ObjectClass superior) {
    public void setSuperior(Set<ObjectClass> superior) {
      this.superior = superior;
    }
@@ -375,7 +395,8 @@
    Map<String, List<String>> emptyMap = Collections.emptyMap();
    new ObjectClass(null, "test", Collections.singleton("test"), null,
        "description", DirectoryServer.getTopObjectClass(), emptySet,
        "description", Collections.singleton(DirectoryServer.getTopObjectClass()),
        emptySet,
        emptySet, ObjectClassType.STRUCTURAL, false, emptyMap);
  }
@@ -494,7 +515,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getOptionalAttributeChain();
@@ -508,6 +529,42 @@
  /**
   * Check the {@link ObjectClass#getOptionalAttributeChain()} method
   * with multiple superiors but no optional attributes of its own.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test
  public void testGetOptionalAttributeChainEmptyMS() throws Exception {
    ObjectClassBuilder builder1 = new ObjectClassBuilder("parent1",
        "1.2.3");
    builder1.addOptionalAttributeTypes(types[0], types[1], types[2]);
    ObjectClass parent1 = builder1.getInstance();
    ObjectClassBuilder builder2 = new ObjectClassBuilder("parent2","3.4.5");
    builder2.addOptionalAttributeTypes(types[3], types[4], types[5]);
    ObjectClass parent2 = builder2.getInstance();
    Set<ObjectClass> superiors = new LinkedHashSet<ObjectClass>();
    superiors.add(parent1);
    superiors.add(parent2);
    ObjectClassBuilder builder3 = new ObjectClassBuilder("child", "6.7.8");
    builder3.setSuperior(superiors);
    ObjectClass child = builder3.getInstance();
    Set<AttributeType> chain = child.getOptionalAttributeChain();
    Assert.assertEquals(chain.size(), 6);
    Assert.assertTrue(chain.contains(types[0]));
    Assert.assertTrue(chain.contains(types[1]));
    Assert.assertTrue(chain.contains(types[2]));
    Assert.assertTrue(chain.contains(types[3]));
    Assert.assertTrue(chain.contains(types[4]));
    Assert.assertTrue(chain.contains(types[5]));
  }
  /**
   * Check the {@link ObjectClass#getOptionalAttributeChain()} method
   * with a superior and some optional attributes of its own.
   *
   * @throws Exception
@@ -522,7 +579,7 @@
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.addOptionalAttributeTypes(types[3], types[4], types[5]);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getOptionalAttributeChain();
@@ -538,6 +595,46 @@
  /**
   * Check the {@link ObjectClass#getOptionalAttributeChain()} method
   * with multiple superiors and some optional attributes of its own.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test
  public void testGetOptionalAttributeChainMS() throws Exception {
    ObjectClassBuilder builder1 = new ObjectClassBuilder("parent1",
        "1.2.3");
    builder1.addOptionalAttributeTypes(types[0], types[1], types[2]);
    ObjectClass parent1 = builder1.getInstance();
    ObjectClassBuilder builder2 = new ObjectClassBuilder("parent2","3.4.5");
    builder2.addOptionalAttributeTypes(types[3], types[4], types[5]);
    ObjectClass parent2 = builder2.getInstance();
    Set<ObjectClass> superiors = new LinkedHashSet<ObjectClass>();
    superiors.add(parent1);
    superiors.add(parent2);
    ObjectClassBuilder builder3 = new ObjectClassBuilder("child", "6.7.8");
    builder3.addOptionalAttributeTypes(types[6], types[7], types[8]);
    builder3.setSuperior(superiors);
    ObjectClass child = builder3.getInstance();
    Set<AttributeType> chain = child.getOptionalAttributeChain();
    Assert.assertEquals(chain.size(), 9);
    Assert.assertTrue(chain.contains(types[0]));
    Assert.assertTrue(chain.contains(types[1]));
    Assert.assertTrue(chain.contains(types[2]));
    Assert.assertTrue(chain.contains(types[3]));
    Assert.assertTrue(chain.contains(types[4]));
    Assert.assertTrue(chain.contains(types[5]));
    Assert.assertTrue(chain.contains(types[6]));
    Assert.assertTrue(chain.contains(types[7]));
    Assert.assertTrue(chain.contains(types[8]));
  }
  /**
   * Check the {@link ObjectClass#getOptionalAttributes()} method with
   * no superior and no optional attributes.
   *
@@ -593,7 +690,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.getOptionalAttributes().isEmpty());
@@ -617,7 +714,7 @@
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.addOptionalAttributeTypes(types[3], types[4], types[5]);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getOptionalAttributes();
@@ -686,7 +783,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getRequiredAttributeChain();
@@ -700,6 +797,42 @@
  /**
   * Check the {@link ObjectClass#getRequiredAttributeChain()} method
   * with multiple superiors but no optional attributes of its own.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test
  public void testGetRequiredAttributeChainEmptyMS() throws Exception {
    ObjectClassBuilder builder = new ObjectClassBuilder("parent1",
        "1.2.3");
    builder.addRequiredAttributeTypes(types[0], types[1], types[2]);
    ObjectClass parent1 = builder.getInstance();
    builder = new ObjectClassBuilder("parent2","3.4.5");
    builder.addRequiredAttributeTypes(types[3], types[4], types[5]);
    ObjectClass parent2 = builder.getInstance();
    Set<ObjectClass> superiors = new LinkedHashSet<ObjectClass>();
    superiors.add(parent1);
    superiors.add(parent2);
    builder = new ObjectClassBuilder("child", "6.7.8");
    builder.setSuperior(superiors);
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getRequiredAttributeChain();
    Assert.assertEquals(chain.size(), 6);
    Assert.assertTrue(chain.contains(types[0]));
    Assert.assertTrue(chain.contains(types[1]));
    Assert.assertTrue(chain.contains(types[2]));
    Assert.assertTrue(chain.contains(types[3]));
    Assert.assertTrue(chain.contains(types[4]));
    Assert.assertTrue(chain.contains(types[5]));
  }
  /**
   * Check the {@link ObjectClass#getRequiredAttributeChain()} method
   * with a superior and some optional attributes of its own.
   *
   * @throws Exception
@@ -714,7 +847,7 @@
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.addRequiredAttributeTypes(types[3], types[4], types[5]);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getRequiredAttributeChain();
@@ -730,6 +863,46 @@
  /**
   * Check the {@link ObjectClass#getRequiredAttributeChain()} method
   * with multiple superiors and some optional attributes of its own.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test
  public void testGetRequiredAttributeChainMS() throws Exception {
     ObjectClassBuilder builder = new ObjectClassBuilder("parent1",
        "1.2.3");
    builder.addRequiredAttributeTypes(types[0], types[1], types[2]);
    ObjectClass parent1 = builder.getInstance();
    builder = new ObjectClassBuilder("parent2","3.4.5");
    builder.addRequiredAttributeTypes(types[3], types[4], types[5]);
    ObjectClass parent2 = builder.getInstance();
    Set<ObjectClass> superiors = new LinkedHashSet<ObjectClass>();
    superiors.add(parent1);
    superiors.add(parent2);
    builder = new ObjectClassBuilder("child", "6.7.8");
    builder.addRequiredAttributeTypes(types[6], types[7], types[8]);
    builder.setSuperior(superiors);
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getRequiredAttributeChain();
    Assert.assertEquals(chain.size(), 9);
    Assert.assertTrue(chain.contains(types[0]));
    Assert.assertTrue(chain.contains(types[1]));
    Assert.assertTrue(chain.contains(types[2]));
    Assert.assertTrue(chain.contains(types[3]));
    Assert.assertTrue(chain.contains(types[4]));
    Assert.assertTrue(chain.contains(types[5]));
    Assert.assertTrue(chain.contains(types[6]));
    Assert.assertTrue(chain.contains(types[7]));
    Assert.assertTrue(chain.contains(types[8]));
  }
  /**
   * Check the {@link ObjectClass#getRequiredAttributes()} method with
   * no superior and no optional attributes.
   *
@@ -785,7 +958,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.getRequiredAttributes().isEmpty());
@@ -809,7 +982,7 @@
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.addRequiredAttributeTypes(types[3], types[4], types[5]);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Set<AttributeType> chain = child.getRequiredAttributes();
@@ -822,7 +995,7 @@
  /**
   * Check the {@link ObjectClass#getSuperiorClass()} method with no
   * Check the {@link ObjectClass#getSuperiorClasses()} method with no
   * superior.
   *
   * @throws Exception
@@ -833,13 +1006,13 @@
    ObjectClassBuilder builder = new ObjectClassBuilder("testType",
        "1.2.3");
    ObjectClass c = builder.getInstance();
    Assert.assertNull(c.getSuperiorClass());
    Assert.assertTrue(c.getSuperiorClasses().isEmpty());
  }
  /**
   * Check the {@link ObjectClass#getSuperiorClass()} method with a
   * Check the {@link ObjectClass#getSuperiorClasses()} method with a
   * superior.
   *
   * @throws Exception
@@ -852,10 +1025,37 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertEquals(child.getSuperiorClass(), parent);
    Assert.assertTrue(child.getSuperiorClasses().contains(parent));
  }
  /**
   * Check the {@link ObjectClass#getSuperiorClasses()} method with multiple
   * superiors.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test
  public void testGetSuperiorClassWithSuperiors() throws Exception {
    ObjectClassBuilder builder = new ObjectClassBuilder("parent1",
        "1.2.3");
    ObjectClass parent1 = builder.getInstance();
    builder = new ObjectClassBuilder("parent2",
            "2.3.4");
    ObjectClass parent2 = builder.getInstance();
    Set<ObjectClass> superiors = new LinkedHashSet<ObjectClass>();
    superiors.add(parent1);
    superiors.add(parent2);
    builder = new ObjectClassBuilder("child", "1.2.3.4");
    builder.setSuperior(superiors);
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.getSuperiorClasses().contains(parent1));
    Assert.assertTrue(child.getSuperiorClasses().contains(parent2));
  }
@@ -895,11 +1095,11 @@
    ObjectClass grandParent = builder.getInstance();
    builder = new ObjectClassBuilder("parent", "1.2.2");
    builder.setSuperior(grandParent);
    builder.setSuperior(Collections.singleton(grandParent));
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(parent.isDescendantOf(grandParent));
@@ -914,6 +1114,45 @@
  /**
   * Check the {@link ObjectClass#isDescendantOf(ObjectClass)} method
   * with multiple superiors.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test
  public void testIsDescendantOfWithMultipleSuperiors() throws Exception {
    ObjectClassBuilder builder = new ObjectClassBuilder(
        "grandParent", "1.2.1");
    ObjectClass grandParent = builder.getInstance();
    builder = new ObjectClassBuilder("parent1", "1.2.2");
    builder.setSuperior(Collections.singleton(grandParent));
    ObjectClass parent1 = builder.getInstance();
    builder = new ObjectClassBuilder("parent2","2.2.2");
    ObjectClass parent2 = builder.getInstance();
    Set<ObjectClass> superiors = new LinkedHashSet<ObjectClass>();
    superiors.add(parent1);
    superiors.add(parent2);
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(superiors);
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(parent1.isDescendantOf(grandParent));
    Assert.assertTrue(child.isDescendantOf(parent1));
    Assert.assertTrue(child.isDescendantOf(parent2));
    Assert.assertTrue(child.isDescendantOf(grandParent));
    Assert.assertFalse(child.isDescendantOf(child));
    Assert.assertFalse(parent1.isDescendantOf(child));
    Assert.assertFalse(parent1.isDescendantOf(parent2));
    Assert.assertFalse(grandParent.isDescendantOf(child));
  }
  /**
   * Create test data for testing the
   * {@link ObjectClass#isExtensibleObject()} method.
   *
@@ -1001,7 +1240,7 @@
    builder.addOptionalAttributeTypes(types[0]);
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.isOptional(types[0]));
@@ -1025,7 +1264,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.addOptionalAttributeTypes(types[1]);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.isOptional(types[0]));
@@ -1087,7 +1326,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("extensibleObject", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass c = builder.getInstance();
    Assert.assertFalse(c.isOptional(types[0]));
@@ -1146,7 +1385,7 @@
    builder.addRequiredAttributeTypes(types[0]);
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.isRequired(types[0]));
@@ -1170,7 +1409,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.addRequiredAttributeTypes(types[1]);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.isRequired(types[0]));
@@ -1234,7 +1473,7 @@
    builder.addRequiredAttributeTypes(types[1]);
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.isRequiredOrOptional(types[0]));
@@ -1261,7 +1500,7 @@
    builder = new ObjectClassBuilder("child", "1.2.3");
    builder.addOptionalAttributeTypes(types[2]);
    builder.addRequiredAttributeTypes(types[3]);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.isRequiredOrOptional(types[0]));
@@ -1326,7 +1565,7 @@
    ObjectClass parent = builder.getInstance();
    builder = new ObjectClassBuilder("extensibleObject", "1.2.3");
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    ObjectClass c = builder.getInstance();
    Assert.assertTrue(c.isRequiredOrOptional(types[0]));
@@ -1367,7 +1606,7 @@
    builder.setDescription("A description");
    builder.setObjectClassType(ObjectClassType.ABSTRACT);
    builder.setObsolete(true);
    builder.setSuperior(parent);
    builder.setSuperior(Collections.singleton(parent));
    builder.addRequiredAttributeTypes(types[0], types[1], types[2]);
    builder.addOptionalAttributeTypes(types[3]);
    builder.addExtraProperty(
@@ -1383,6 +1622,80 @@
  /**
   * Create test data for testing different combinations of superiors.
   *
   * @return Returns the array of test data.
   */
  @DataProvider(name = "superiorData")
  public Object[][] createSuperiorData() {
    ObjectClassBuilder builder = new ObjectClassBuilder(
        "parent1", "1.1");
    builder.setObjectClassType(ObjectClassType.ABSTRACT);
    ObjectClass parent1 = builder.getInstance();
    builder = new ObjectClassBuilder(
        "parent2", "1.2");
    builder.setObjectClassType(ObjectClassType.ABSTRACT);
    ObjectClass parent2 = builder.getInstance();
    builder = new ObjectClassBuilder(
        "parent3", "1.3");
    builder.setObjectClassType(ObjectClassType.STRUCTURAL);
    ObjectClass parent3 = builder.getInstance();
    builder = new ObjectClassBuilder(
        "parent4", "1.4");
    ObjectClass parent4 = builder.getInstance();
    builder = new ObjectClassBuilder(
        "parent5", "1.5");
    builder.setObjectClassType(ObjectClassType.AUXILIARY);
    ObjectClass parent5 = builder.getInstance();
    builder = new ObjectClassBuilder(
        "parent6", "1.6");
    builder.setObjectClassType(ObjectClassType.AUXILIARY);
    ObjectClass parent6 = builder.getInstance();
    return new Object[][] { { parent1, parent2, ObjectClassType.ABSTRACT,true },
        { parent3, parent4, ObjectClassType.STRUCTURAL,true },
        { parent5, parent6, ObjectClassType.AUXILIARY,true }
    };
  }
  /**
   * Check incompatible superiors.
   *
   * @param parent1
   *          First superior
   * @param parent2
   *          Second superior
   * @param type
   *          The object class type.
   * @param isValid
   *          Whether the superior combination is valid.
   */
  @Test(dataProvider = "superiorData")
  public void testMultipleSuperiors(ObjectClass parent1,
          ObjectClass parent2,
          ObjectClassType type,
          boolean isValid) throws Exception {
    ObjectClassBuilder builder = new ObjectClassBuilder("testType",
        "1.2.3");
    builder.setObjectClassType(type);
    Set<ObjectClass> superiors = new LinkedHashSet<ObjectClass>();
    superiors.add(parent1);
    superiors.add(parent2);
    builder.setSuperior(superiors);
    ObjectClass child = builder.getInstance();
    Assert.assertTrue(child.getSuperiorClasses().size()==2);
  }
  /**
   * {@inheritDoc}
   */
  @Override