From 85811b64468e9b7a876bd352a0299b904a53a3fb Mon Sep 17 00:00:00 2001
From: ludovicp <ludovicp@localhost>
Date: Mon, 31 May 2010 12:16:23 +0000
Subject: [PATCH] Fix for Issue #615. Add support for multiple object-class inheritance. Support added in the schema, core server and tools including Control-Panel

---
 opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java                    |    2 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/MainMenuBar.java                                |    2 
 opends/src/quicksetup/org/opends/quicksetup/installer/ui/RuntimeOptionsPanel.java                       |    4 
 opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedEvent.java       |   79 +
 opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java              |   10 
 opends/src/guitools/org/opends/guitools/controlpanel/browser/NodeRefresher.java                         |    2 
 opends/src/quicksetup/org/opends/quicksetup/installer/ui/JavaArgumentsDialog.java                       |   10 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/StandardObjectClassPanel.java                   |   95 +
 opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java                                 |   10 
 opends/src/server/org/opends/server/schema/ObjectClassSyntax.java                                       |  171 +--
 opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java                 |   49 
 opends/src/server/org/opends/server/workflowelement/ndb/NDBAddOperation.java                            |   18 
 opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java          |   11 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/SelectObjectClassesPanel.java                   |  291 ++++++
 opends/src/guitools/org/opends/guitools/controlpanel/ui/DBEnvironmentMonitoringPanel.java               |    4 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java                        |  103 +-
 opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java                        |    2 
 opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedListener.java    |   45 +
 opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java            |    4 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/components/SuperiorObjectClassesEditor.java     |  392 +++++++++
 opends/src/guitools/org/opends/guitools/controlpanel/browser/AbstractNodeTask.java                      |    4 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java           |    4 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/RefreshOptionsPanel.java                        |   14 
 opends/src/quicksetup/org/opends/quicksetup/installer/ui/SelectAliasDialog.java                         |   14 
 opends/src/server/org/opends/server/backends/SchemaBackend.java                                         |   32 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java                             |   30 
 opends/src/server/org/opends/server/util/StaticUtils.java                                               |   24 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/SchemaElementComboBoxCellRenderer.java |    9 
 opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestObjectClass.java                  |  373 ++++++++
 opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java                       |    4 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java                           |    2 
 opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java                    |   20 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java                         |  158 +-
 opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java                      |    4 
 opends/src/server/org/opends/server/core/DirectoryServer.java                                           |    6 
 opends/src/server/org/opends/server/types/Schema.java                                                   |    5 
 opends/src/server/org/opends/server/types/ObjectClass.java                                              |   82 +
 opends/resource/schema/00-core.ldif                                                                     |   10 
 opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java                             |   10 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java                     |  169 ++--
 opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java                     |   20 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java                          |   77 +
 opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java                                    |    2 
 opends/src/messages/messages/admin_tool.properties                                                      |   29 
 opends/src/guitools/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java                   |    9 
 opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java                                |   93 ++
 46 files changed, 1,949 insertions(+), 559 deletions(-)

diff --git a/opends/resource/schema/00-core.ldif b/opends/resource/schema/00-core.ldif
index 2d92941..3853601 100644
--- a/opends/resource/schema/00-core.ldif
+++ b/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' )
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/browser/AbstractNodeTask.java b/opends/src/guitools/org/opends/guitools/controlpanel/browser/AbstractNodeTask.java
index 942d6c8..115cb4e 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/browser/AbstractNodeTask.java
+++ b/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;
   }
 
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/browser/NodeRefresher.java b/opends/src/guitools/org/opends/guitools/controlpanel/browser/NodeRefresher.java
index f7e3c7c..3123728 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/browser/NodeRefresher.java
+++ b/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) {
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java
index 80da30d..c3c8fe7 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java
+++ b/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++)
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedEvent.java b/opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedEvent.java
new file mode 100644
index 0000000..60e558b
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedEvent.java
@@ -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);
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedListener.java b/opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedListener.java
new file mode 100644
index 0000000..c4d93d9
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/event/SuperiorObjectClassesChangedListener.java
@@ -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);
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java b/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java
index 2e27b76..61f3ad0 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java
+++ b/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);
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java b/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java
index 9481a5b..5881523 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java
+++ b/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(),
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java b/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java
index 3a46366..4541963 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java
+++ b/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(),
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
index d19b798..3c485d9 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
+++ b/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);
         }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java
index a6c4fab..9723594 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java
+++ b/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();
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java
index 4109591..249f47c 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java
+++ b/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())
       {
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/DBEnvironmentMonitoringPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/DBEnvironmentMonitoringPanel.java
index f664349..493d1c9 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/DBEnvironmentMonitoringPanel.java
+++ b/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);
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MainMenuBar.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/MainMenuBar.java
index dfcecec..9fdcf6c 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MainMenuBar.java
+++ b/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();
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java
index 3567d31..4b366db 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java
+++ b/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();
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java
index e404f17..8442a26 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java
+++ b/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;
  }
 
  /**
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java
index de0954a..db1e02d 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java
+++ b/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(),
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/RefreshOptionsPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/RefreshOptionsPanel.java
index 011d92d..a089f0e 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/RefreshOptionsPanel.java
+++ b/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));
     }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/SelectObjectClassesPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/SelectObjectClassesPanel.java
new file mode 100644
index 0000000..f6d8eaf
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/SelectObjectClassesPanel.java
@@ -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);
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java
index cf4413f..33aad38 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java
+++ b/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;
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StandardObjectClassPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/StandardObjectClassPanel.java
index 4836d0a..1f7c1e5 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StandardObjectClassPanel.java
+++ b/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.
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
index 0255778..b30d736 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
+++ b/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));
+      }
+    }
+  }
 }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java
index 9ae1234..d1f4508 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java
+++ b/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;
   }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java
index ad80e04..a1a7261 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java
+++ b/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;
+  }
 }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java
index c93d8db..ac4406d 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java
+++ b/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());
     }
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/SuperiorObjectClassesEditor.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/SuperiorObjectClassesEditor.java
new file mode 100644
index 0000000..b239090
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/SuperiorObjectClassesEditor.java
@@ -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);
+    }
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/SchemaElementComboBoxCellRenderer.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/SchemaElementComboBoxCellRenderer.java
index 2949fac..b8a7926 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/SchemaElementComboBoxCellRenderer.java
+++ b/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,
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java b/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
index f67322f..96fd760 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
+++ b/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;
+        }
+      }
+    }
+  }
 }
diff --git a/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java b/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
index 26282cb..5766b3e 100644
--- a/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
+++ b/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;
diff --git a/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java b/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
index 17f049e..305345f 100644
--- a/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
+++ b/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());
diff --git a/opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java b/opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java
index 3e07e4c..4e93d65 100644
--- a/opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java
+++ b/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();
diff --git a/opends/src/messages/messages/admin_tool.properties b/opends/src/messages/messages/admin_tool.properties
index e12d4da..1bb6724 100644
--- a/opends/src/messages/messages/admin_tool.properties
+++ b/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:
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/JavaArgumentsDialog.java b/opends/src/quicksetup/org/opends/quicksetup/installer/ui/JavaArgumentsDialog.java
index 948fb03..030df19 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/JavaArgumentsDialog.java
+++ b/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();
             }
           }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/RuntimeOptionsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/installer/ui/RuntimeOptionsPanel.java
index 67ef7eb..2c6e557 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/RuntimeOptionsPanel.java
+++ b/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(
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java b/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java
index 23b87e8..6303404 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java
+++ b/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();
             }
           }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SelectAliasDialog.java b/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SelectAliasDialog.java
index 247da0b..ee0b585 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SelectAliasDialog.java
+++ b/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();
   }
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java
index 5997c24..e61bf26 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java
+++ b/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();
diff --git a/opends/src/server/org/opends/server/backends/SchemaBackend.java b/opends/src/server/org/opends/server/backends/SchemaBackend.java
index 5919973..7d813e1 100644
--- a/opends/src/server/org/opends/server/backends/SchemaBackend.java
+++ b/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);
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 9a83f6b..deaba0e 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/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);
     }
 
diff --git a/opends/src/server/org/opends/server/schema/ObjectClassSyntax.java b/opends/src/server/org/opends/server/schema/ObjectClassSyntax.java
index 8ba85cf..f89c918 100644
--- a/opends/src/server/org/opends/server/schema/ObjectClassSyntax.java
+++ b/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;
   }
 
 
diff --git a/opends/src/server/org/opends/server/types/ObjectClass.java b/opends/src/server/org/opends/server/types/ObjectClass.java
index d49b733..9971281 100644
--- a/opends/src/server/org/opends/server/types/ObjectClass.java
+++ b/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 @@
       }
     }
   }
-}
+  }
diff --git a/opends/src/server/org/opends/server/types/Schema.java b/opends/src/server/org/opends/server/types/Schema.java
index 67094d8..f6ce22d 100644
--- a/opends/src/server/org/opends/server/types/Schema.java
+++ b/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);
diff --git a/opends/src/server/org/opends/server/util/StaticUtils.java b/opends/src/server/org/opends/server/util/StaticUtils.java
index 4ea46c1..fc1323a 100644
--- a/opends/src/server/org/opends/server/util/StaticUtils.java
+++ b/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);
+        }
       }
     }
   }
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
index a10e64b..de6a48f 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
+++ b/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);
+        }
       }
     }
   }
diff --git a/opends/src/server/org/opends/server/workflowelement/ndb/NDBAddOperation.java b/opends/src/server/org/opends/server/workflowelement/ndb/NDBAddOperation.java
index d0b4872..9c8635f 100644
--- a/opends/src/server/org/opends/server/workflowelement/ndb/NDBAddOperation.java
+++ b/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);
+            }
           }
         }
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestObjectClass.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestObjectClass.java
index 2cd2fe1..b32478d 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestObjectClass.java
+++ b/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

--
Gitblit v1.10.0