From 92942bc98880793237d38d87db45abd5537d3f62 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Thu, 17 Dec 2009 21:11:04 +0000
Subject: [PATCH] Fix for issue 3601 (Control Panel: unable to modify schema objects or attributes)

---
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java        |  300 --
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java    |  255 ++
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java |  444 ++++
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomAttributePanel.java       | 1151 +++++++++++
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java          |  439 ++-
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java      |  328 +++
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java     | 1065 ++++++++++
 opendj-sdk/opends/src/messages/messages/admin_tool.properties                                      |  129 
 /dev/null                                                                                          |  295 ---
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/NewSchemaElementsTask.java    |  824 ++++++++
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java         |   48 
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/SchemaBrowserRightPanel.java    |   43 
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/ControlPanelLog.java          |    4 
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewAttributePanel.java          |  331 --
 opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/Task.java                     |   56 
 15 files changed, 4,593 insertions(+), 1,119 deletions(-)

diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java
index de93f67..2e27b76 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/DeleteSchemaElementsTask.java
@@ -32,8 +32,12 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.naming.NamingException;
@@ -60,6 +64,7 @@
 import org.opends.server.types.ModificationType;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.types.OpenDsException;
+import org.opends.server.types.Schema;
 import org.opends.server.types.SchemaFileElement;
 import org.opends.server.util.LDIFReader;
 import org.opends.server.util.LDIFWriter;
@@ -69,24 +74,94 @@
  */
 public class DeleteSchemaElementsTask extends Task
 {
-  ArrayList<ObjectClass> ocsToDelete = new ArrayList<ObjectClass>();
-  ArrayList<AttributeType> attrsToDelete = new ArrayList<AttributeType>();
-  private Set<String> backendSet;
+  // The list of object classes that the user asked to delete.
+  LinkedHashSet<ObjectClass> providedOcsToDelete =
+    new LinkedHashSet<ObjectClass>();
+  // The list of attributes that the user asked to delete.
+  LinkedHashSet<AttributeType> providedAttrsToDelete =
+    new LinkedHashSet<AttributeType>();
+  // The list of object classes that will be actually deleted (some might be
+  // recreated).
+  LinkedHashSet<ObjectClass> ocsToDelete = new LinkedHashSet<ObjectClass>();
+  // The list of attributes that will be actually deleted (some might be
+  // recreated).
+  LinkedHashSet<AttributeType> attrsToDelete =
+    new LinkedHashSet<AttributeType>();
+  // The list of object classes that will be recreated.
+  LinkedHashSet<ObjectClass> ocsToAdd = new LinkedHashSet<ObjectClass>();
+  // The list of attributes that will be recreated.
+  LinkedHashSet<AttributeType> attrsToAdd = new LinkedHashSet<AttributeType>();
 
   /**
    * Constructor of the task.
    * @param info the control panel information.
    * @param dlg the progress dialog where the task progress will be displayed.
-   * @param ocsToDelete the object classes that must be deleted.
-   * @param attrsToDelete the attributes that must be deleted.
+   * @param ocsToDelete the object classes that must be deleted (ordered).
+   * @param attrsToDelete the attributes that must be deleted (ordered).
    */
   public DeleteSchemaElementsTask(ControlPanelInfo info, ProgressDialog dlg,
-      List<ObjectClass> ocsToDelete, List<AttributeType> attrsToDelete)
+      LinkedHashSet<ObjectClass> ocsToDelete,
+      LinkedHashSet<AttributeType> attrsToDelete)
   {
     super(info, dlg);
-    this.ocsToDelete.addAll(ocsToDelete);
-    this.attrsToDelete.addAll(attrsToDelete);
-    backendSet = new HashSet<String>();
+
+    this.providedOcsToDelete.addAll(ocsToDelete);
+    this.providedAttrsToDelete.addAll(attrsToDelete);
+
+    Schema schema = info.getServerDescriptor().getSchema();
+    LinkedHashSet<AttributeType> allAttrsToDelete =
+      DeleteSchemaElementsTask.getOrderedAttributesToDelete(attrsToDelete,
+          schema);
+    LinkedHashSet<ObjectClass> allOcsToDelete = null;
+    if (!attrsToDelete.isEmpty())
+    {
+      allOcsToDelete =
+        DeleteSchemaElementsTask.getOrderedObjectClassesToDeleteFromAttrs(
+          attrsToDelete, schema);
+    }
+    if (!ocsToDelete.isEmpty())
+    {
+      if (allOcsToDelete == null)
+      {
+      allOcsToDelete =
+        DeleteSchemaElementsTask.getOrderedObjectClassesToDelete(
+            ocsToDelete, schema);
+      }
+      else
+      {
+        allOcsToDelete.addAll(
+            DeleteSchemaElementsTask.getOrderedObjectClassesToDelete(
+                ocsToDelete, schema));
+      }
+    }
+    ArrayList<AttributeType> lAttrsToDelete =
+      new ArrayList<AttributeType>(allAttrsToDelete);
+    for (int i = lAttrsToDelete.size() - 1; i >= 0; i--)
+    {
+      AttributeType attrToDelete = lAttrsToDelete.get(i);
+      if (!attrsToDelete.contains(attrToDelete))
+      {
+        AttributeType attrToAdd = getAttributeToAdd(attrToDelete);
+        if (attrToAdd != null)
+        {
+          attrsToAdd.add(attrToAdd);
+        }
+      }
+    }
+
+    ArrayList<ObjectClass> lOcsToDelete =
+      new ArrayList<ObjectClass>(allOcsToDelete);
+    for (int i = lOcsToDelete.size() - 1; i >= 0; i--)
+    {
+      ObjectClass ocToDelete = lOcsToDelete.get(i);
+      if (!ocsToDelete.contains(ocToDelete))
+      {
+        ocsToAdd.add(getObjectClassToAdd(lOcsToDelete.get(i)));
+      }
+    }
+
+    this.ocsToDelete.addAll(allOcsToDelete);
+    this.attrsToDelete.addAll(allAttrsToDelete);
   }
 
   /**
@@ -94,7 +169,7 @@
    */
   public Set<String> getBackends()
   {
-    return backendSet;
+    return Collections.emptySet();
   }
 
   /**
@@ -103,7 +178,17 @@
   public boolean canLaunch(Task taskToBeLaunched,
       Collection<Message> incompatibilityReasons)
   {
-    return true;
+    boolean canLaunch = true;
+    if (state == State.RUNNING &&
+        (taskToBeLaunched.getType() == Task.Type.DELETE_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.MODIFY_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.NEW_SCHEMA_ELEMENT))
+    {
+      incompatibilityReasons.add(getIncompatibilityMessage(this,
+            taskToBeLaunched));
+      canLaunch = false;
+    }
+    return canLaunch;
   }
 
   /**
@@ -111,18 +196,7 @@
    */
   public Type getType()
   {
-    if (attrsToDelete.isEmpty())
-    {
-      return Type.DELETE_OBJECTCLASS;
-    }
-    else if (ocsToDelete.isEmpty())
-    {
-      return Type.DELETE_ATTRIBUTE;
-    }
-    else
-    {
-      return Type.DELETE_OBJECTCLASS;
-    }
+    return Type.NEW_SCHEMA_ELEMENT;
   }
 
   /**
@@ -156,9 +230,9 @@
   /**
    * {@inheritDoc}
    */
-  protected ArrayList<String> getCommandLineArguments()
+  protected List<String> getCommandLineArguments()
   {
-    return new ArrayList<String>();
+    return Collections.emptyList();
   }
 
   /**
@@ -178,8 +252,9 @@
     final boolean[] isFirst = {true};
     final int totalNumber = ocsToDelete.size() + attrsToDelete.size();
     int numberDeleted = 0;
-    for (final ObjectClass objectClass : ocsToDelete)
+    for (ObjectClass objectClass : ocsToDelete)
     {
+      final ObjectClass fObjectclass = objectClass;
       SwingUtilities.invokeLater(new Runnable()
       {
         public void run()
@@ -189,11 +264,11 @@
             getProgressDialog().appendProgressHtml("<br><br>");
           }
           isFirst[0] = false;
-          printEquivalentCommandToDelete(objectClass);
+          printEquivalentCommandToDelete(fObjectclass);
           getProgressDialog().appendProgressHtml(
               Utilities.getProgressWithPoints(
                   INFO_CTRL_PANEL_DELETING_OBJECTCLASS.get(
-                  objectClass.getNameOrOID()),
+                      fObjectclass.getNameOrOID()),
                   ColorAndFontConstants.progressFont));
         }
       });
@@ -236,8 +311,9 @@
       });
     }
 
-    for (final AttributeType attribute : attrsToDelete)
+    for (AttributeType attribute : attrsToDelete)
     {
+      final AttributeType fAttribute = attribute;
       SwingUtilities.invokeLater(new Runnable()
       {
         public void run()
@@ -247,11 +323,11 @@
             getProgressDialog().appendProgressHtml("<br><br>");
           }
           isFirst[0] = false;
-          printEquivalentCommandToDelete(attribute);
+          printEquivalentCommandToDelete(fAttribute);
           getProgressDialog().appendProgressHtml(
               Utilities.getProgressWithPoints(
                   INFO_CTRL_PANEL_DELETING_ATTRIBUTE.get(
-                  attribute.getNameOrOID()),
+                      fAttribute.getNameOrOID()),
                   ColorAndFontConstants.progressFont));
         }
       });
@@ -296,6 +372,25 @@
       });
     }
 
+    if (!ocsToAdd.isEmpty() || !attrsToAdd.isEmpty())
+    {
+      SwingUtilities.invokeLater(new Runnable()
+      {
+        public void run()
+        {
+          getProgressDialog().appendProgressHtml(Utilities.applyFont(
+              "<br><br>"+
+              INFO_CTRL_PANEL_EXPLANATION_TO_DELETE_REFERENCED_ELEMENTS.get()+
+              "<br><br>",
+              ColorAndFontConstants.progressFont));
+        }
+      });
+
+      NewSchemaElementsTask createTask =
+        new NewSchemaElementsTask(getInfo(), getProgressDialog(), ocsToAdd,
+            attrsToAdd);
+      createTask.runTask();
+    }
   }
 
   /**
@@ -431,9 +526,19 @@
     String attrValue = getSchemaFileAttributeValue(element);
     if (!isServerRunning())
     {
+      Message msg;
+      if (element instanceof AttributeType)
+      {
+        msg = INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_ATTRIBUTE_OFFLINE.get(
+            element.getNameOrOID(), schemaFile);
+      }
+      else
+      {
+        msg = INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_OBJECTCLASS_OFFLINE.get(
+            element.getNameOrOID(), schemaFile);
+      }
       getProgressDialog().appendProgressHtml(Utilities.applyFont(
-          INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_SCHEMA_ELEMENT_OFFLINE.get(
-              schemaFile)+"<br><b>"+
+          msg+"<br><b>"+
           attrName+": "+attrValue+"</b><br><br>",
           ColorAndFontConstants.progressFont));
     }
@@ -447,10 +552,21 @@
       String equiv = getEquivalentCommandLine(getCommandLinePath("ldapmodify"),
           args);
 
+      Message msg;
+      if (element instanceof AttributeType)
+      {
+        msg = INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_ATTRIBUTE_ONLINE.get(
+            element.getNameOrOID());
+      }
+      else
+      {
+        msg = INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_OBJECTCLASS_ONLINE.get(
+            element.getNameOrOID());
+      }
+
       StringBuilder sb = new StringBuilder();
       sb.append(
-          INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_SCHEMA_ELEMENT_ONLINE.get()+
-          "<br><b>");
+          msg+"<br><b>");
       sb.append(equiv);
       sb.append("<br>");
       sb.append("dn: cn=schema<br>");
@@ -462,4 +578,262 @@
           ColorAndFontConstants.progressFont));
     }
   }
+
+  private AttributeType getAttributeToAdd(AttributeType attrToDelete)
+  {
+    AttributeType attrToAdd;
+    boolean isSuperior = false;
+    AttributeType newSuperior = attrToDelete.getSuperiorType();
+    for (AttributeType attr : providedAttrsToDelete)
+    {
+      if (attr.equals(attrToDelete.getSuperiorType()))
+      {
+        isSuperior = true;
+        newSuperior = attr.getSuperiorType();
+        while (newSuperior != null &&
+            providedAttrsToDelete.contains(newSuperior))
+        {
+          newSuperior = newSuperior.getSuperiorType();
+        }
+        break;
+      }
+    }
+    if (isSuperior)
+    {
+      ArrayList<String> allNames = new ArrayList<String>();
+      for (String str : attrToDelete.getNormalizedNames())
+      {
+        allNames.add(str);
+      }
+      Map<String, List<String>> extraProperties =
+        cloneExtraProperties(attrToDelete);
+      attrToAdd = new AttributeType(
+          "",
+          attrToDelete.getPrimaryName(),
+          allNames,
+          attrToDelete.getOID(),
+          attrToDelete.getDescription(),
+          null,
+          attrToDelete.getSyntax(),
+          attrToDelete.getApproximateMatchingRule(),
+          attrToDelete.getEqualityMatchingRule(),
+          attrToDelete.getOrderingMatchingRule(),
+          attrToDelete.getSubstringMatchingRule(),
+          attrToDelete.getUsage(),
+          attrToDelete.isCollective(),
+          attrToDelete.isNoUserModification(),
+          attrToDelete.isObsolete(),
+          attrToDelete.isSingleValue(),
+          extraProperties);
+    }
+    else
+    {
+      // Nothing to be changed in the definition of the attribute itself.
+      attrToAdd = attrToDelete;
+    }
+    return attrToAdd;
+  }
+
+  private ObjectClass getObjectClassToAdd(ObjectClass ocToDelete)
+  {
+    ObjectClass ocToAdd;
+    boolean containsAttribute = false;
+    for (AttributeType attr : providedAttrsToDelete)
+    {
+      if(ocToDelete.getRequiredAttributeChain().contains(attr) ||
+      ocToDelete.getOptionalAttributeChain().contains(attr))
+      {
+        containsAttribute = true;
+        break;
+      }
+    }
+    boolean hasSuperior = false;
+    ObjectClass newSuperior = ocToDelete.getSuperiorClass();
+    for (ObjectClass oc : providedOcsToDelete)
+    {
+      if (ocToDelete.getSuperiorClass().equals(oc))
+      {
+        hasSuperior = true;
+        newSuperior = oc.getSuperiorClass();
+        while (newSuperior != null &&
+            providedOcsToDelete.contains(newSuperior))
+        {
+          newSuperior = newSuperior.getSuperiorClass();
+        }
+        break;
+      }
+    }
+    if (containsAttribute || hasSuperior)
+    {
+      ArrayList<String> allNames = new ArrayList<String>();
+      for (String str : ocToDelete.getNormalizedNames())
+      {
+        allNames.add(str);
+      }
+      Map<String, List<String>> extraProperties =
+        cloneExtraProperties(ocToDelete);
+      Set<AttributeType> required;
+      Set<AttributeType> optional;
+      if (containsAttribute)
+      {
+        required = new HashSet<AttributeType>(
+            ocToDelete.getRequiredAttributes());
+        optional = new HashSet<AttributeType>(
+            ocToDelete.getOptionalAttributes());
+        required.removeAll(providedAttrsToDelete);
+        optional.removeAll(providedAttrsToDelete);
+      }
+      else
+      {
+        required = ocToDelete.getRequiredAttributes();
+        optional = ocToDelete.getOptionalAttributes();
+      }
+      ocToAdd = new ObjectClass("",
+          ocToDelete.getPrimaryName(),
+          allNames,
+          ocToDelete.getOID(),
+          ocToDelete.getDescription(),
+          newSuperior,
+          required,
+          optional,
+          ocToDelete.getObjectClassType(),
+          ocToDelete.isObsolete(),
+          extraProperties);
+    }
+    else
+    {
+      // Nothing to be changed in the definition of the object class itself.
+      ocToAdd = ocToDelete;
+    }
+    return ocToAdd;
+  }
+
+
+  /**
+   * Returns an ordered set of the attributes that must be deleted.
+   * @param attrsToDelete the attributes to be deleted.
+   * @param schema the server schema.
+   * @return an ordered list of the attributes that must be deleted.
+   */
+  public static LinkedHashSet<AttributeType> getOrderedAttributesToDelete(
+      Collection<AttributeType> attrsToDelete, Schema schema)
+  {
+    LinkedHashSet<AttributeType> orderedAttributes =
+      new LinkedHashSet<AttributeType>();
+    for (AttributeType attribute : attrsToDelete)
+    {
+      orderedAttributes.addAll(getOrderedChildrenToDelete(attribute, schema));
+      orderedAttributes.add(attribute);
+    }
+    return orderedAttributes;
+  }
+
+  /**
+   * Returns an ordered list of the object classes that must be deleted.
+   * @param ocsToDelete the object classes to be deleted.
+   * @param schema the server schema.
+   * @return an ordered list of the object classes that must be deleted.
+   */
+  public static LinkedHashSet<ObjectClass> getOrderedObjectClassesToDelete(
+      Collection<ObjectClass> ocsToDelete, Schema schema)
+  {
+    LinkedHashSet<ObjectClass> orderedOcs = new LinkedHashSet<ObjectClass>();
+    for (ObjectClass oc : ocsToDelete)
+    {
+      orderedOcs.addAll(getOrderedChildrenToDelete(oc, schema));
+      orderedOcs.add(oc);
+    }
+    return orderedOcs;
+  }
+
+  /**
+   * Returns an ordered list of the object classes that must be deleted when
+   * deleting a list of attributes that must be deleted.
+   * @param attrsToDelete the attributes to be deleted.
+   * @param schema the server schema.
+   * @return an ordered list of the object classes that must be deleted when
+   * deleting a list of attributes that must be deleted.
+   */
+  public static LinkedHashSet<ObjectClass>
+  getOrderedObjectClassesToDeleteFromAttrs(
+      Collection<AttributeType> attrsToDelete, Schema schema)
+  {
+    LinkedHashSet<ObjectClass> orderedOcs = new LinkedHashSet<ObjectClass>();
+    ArrayList<ObjectClass> dependentClasses = new ArrayList<ObjectClass>();
+    for (AttributeType attr : attrsToDelete)
+    {
+      for (ObjectClass oc : schema.getObjectClasses().values())
+      {
+        if (oc.getRequiredAttributeChain().contains(attr))
+        {
+          dependentClasses.add(oc);
+        }
+        else if (oc.getOptionalAttributeChain().contains(attr))
+        {
+          dependentClasses.add(oc);
+        }
+      }
+    }
+    for (ObjectClass oc : dependentClasses)
+    {
+      orderedOcs.addAll(getOrderedChildrenToDelete(oc, schema));
+      orderedOcs.add(oc);
+    }
+    return orderedOcs;
+  }
+
+  /**
+   * Clones the extra properties of the provided schema element.  This can
+   * be used when copying schema elements.
+   * @param element the schema element.
+   * @return the extra properties of the provided schema element.
+   */
+  public static Map<String, List<String>> cloneExtraProperties(
+      CommonSchemaElements element)
+  {
+    Map<String, List<String>> extraProperties =
+      new HashMap<String, List<String>>();
+    for (String name : element.getExtraPropertyNames())
+    {
+      List<String> values = new ArrayList<String>();
+      Iterable<String> properties = element.getExtraProperty(name);
+      for (String v : properties)
+      {
+        values.add(v);
+      }
+      extraProperties.put(name, values);
+    }
+    return extraProperties;
+  }
+
+
+  private static LinkedHashSet<AttributeType> getOrderedChildrenToDelete(
+      AttributeType attribute, Schema schema)
+  {
+    LinkedHashSet<AttributeType> children = new LinkedHashSet<AttributeType>();
+    for (AttributeType attr : schema.getAttributeTypes().values())
+    {
+      if (attribute.equals(attr.getSuperiorType()))
+      {
+        children.addAll(getOrderedChildrenToDelete(attr, schema));
+        children.add(attr);
+      }
+    }
+    return children;
+  }
+
+  private static LinkedHashSet<ObjectClass> getOrderedChildrenToDelete(
+      ObjectClass objectClass, Schema schema)
+  {
+    LinkedHashSet<ObjectClass> children = new LinkedHashSet<ObjectClass>();
+    for (ObjectClass oc : schema.getObjectClasses().values())
+    {
+      if (objectClass.equals(oc.getSuperiorClass()))
+      {
+        children.addAll(getOrderedChildrenToDelete(oc, schema));
+        children.add(oc);
+      }
+    }
+    return children;
+  }
 }
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java
new file mode 100644
index 0000000..9481a5b
--- /dev/null
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyAttributeTask.java
@@ -0,0 +1,328 @@
+/*
+ * 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 2009 Sun Microsystems, Inc.
+ */
+package org.opends.guitools.controlpanel.task;
+
+import static org.opends.messages.AdminToolMessages.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.SwingUtilities;
+
+import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
+import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
+import org.opends.guitools.controlpanel.ui.ProgressDialog;
+import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.messages.Message;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.OpenDsException;
+import org.opends.server.types.Schema;
+
+/**
+ * The task that is in charge of modifying an attribute definition (and all
+ * the references to this attribute).
+ *
+ */
+public class ModifyAttributeTask extends Task
+{
+  private AttributeType oldAttribute;
+  private AttributeType newAttribute;
+
+  /**
+   * The constructor of the task.
+   * @param info the control panel info.
+   * @param dlg the progress dialog that shows the progress of the task.
+   * @param oldAttribute the old attribute definition.
+   * @param newAttribute the new attribute definition.
+   */
+  public ModifyAttributeTask(ControlPanelInfo info, ProgressDialog dlg,
+      AttributeType oldAttribute, AttributeType newAttribute)
+  {
+    super(info, dlg);
+    if (oldAttribute == null)
+    {
+      throw new IllegalArgumentException("oldAttribute cannot be null.");
+    }
+    if (newAttribute == null)
+    {
+      throw new IllegalArgumentException("newAttribute cannot be null.");
+    }
+    this.oldAttribute = oldAttribute;
+    this.newAttribute = newAttribute;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Type getType()
+  {
+    return Type.MODIFY_SCHEMA_ELEMENT;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Message getTaskDescription()
+  {
+    return INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TASK_DESCRIPTION.get(
+        oldAttribute.getNameOrOID());
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean canLaunch(Task taskToBeLaunched,
+      Collection<Message> incompatibilityReasons)
+  {
+    boolean canLaunch = true;
+    if (state == State.RUNNING &&
+        (taskToBeLaunched.getType() == Task.Type.DELETE_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.MODIFY_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.NEW_SCHEMA_ELEMENT))
+    {
+      incompatibilityReasons.add(getIncompatibilityMessage(this,
+            taskToBeLaunched));
+      canLaunch = false;
+    }
+    return canLaunch;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Set<String> getBackends()
+  {
+    return Collections.emptySet();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected List<String> getCommandLineArguments()
+  {
+    return Collections.emptyList();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getCommandLinePath()
+  {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void runTask()
+  {
+    try
+    {
+      updateSchema();
+      state = State.FINISHED_SUCCESSFULLY;
+    }
+    catch (Throwable t)
+    {
+      // TODO
+      //revertChanges();
+      lastException = t;
+      state = State.FINISHED_WITH_ERROR;
+    }
+  }
+
+  private AttributeType getAttributeToAdd(AttributeType attrToDelete)
+  {
+    AttributeType attrToAdd;
+    if (attrToDelete.equals(oldAttribute))
+    {
+      attrToAdd = newAttribute;
+    }
+    else
+    {
+      if (oldAttribute.equals(attrToDelete.getSuperiorType()))
+      {
+        ArrayList<String> allNames = new ArrayList<String>();
+        for (String str : attrToDelete.getNormalizedNames())
+        {
+          allNames.add(str);
+        }
+        Map<String, List<String>> extraProperties =
+          DeleteSchemaElementsTask.cloneExtraProperties(attrToDelete);
+        AttributeType newSuperior = newAttribute;
+        attrToAdd = new AttributeType(
+            "",
+            attrToDelete.getPrimaryName(),
+            allNames,
+            attrToDelete.getOID(),
+            attrToDelete.getDescription(),
+            newSuperior,
+            attrToDelete.getSyntax(),
+            attrToDelete.getApproximateMatchingRule(),
+            attrToDelete.getEqualityMatchingRule(),
+            attrToDelete.getOrderingMatchingRule(),
+            attrToDelete.getSubstringMatchingRule(),
+            attrToDelete.getUsage(),
+            attrToDelete.isCollective(),
+            attrToDelete.isNoUserModification(),
+            attrToDelete.isObsolete(),
+            attrToDelete.isSingleValue(),
+            extraProperties);
+      }
+      else
+      {
+        // Nothing to be changed in the definition of the attribute itself.
+        attrToAdd = attrToDelete;
+      }
+    }
+    return attrToAdd;
+  }
+
+  private ObjectClass getObjectClassToAdd(ObjectClass ocToDelete)
+  {
+    ObjectClass ocToAdd;
+    boolean containsAttribute =
+      ocToDelete.getRequiredAttributeChain().contains(oldAttribute) ||
+      ocToDelete.getOptionalAttributeChain().contains(oldAttribute);
+    if (containsAttribute)
+    {
+      ArrayList<String> allNames = new ArrayList<String>();
+      for (String str : ocToDelete.getNormalizedNames())
+      {
+        allNames.add(str);
+      }
+      Map<String, List<String>> extraProperties =
+        DeleteSchemaElementsTask.cloneExtraProperties(ocToDelete);
+      Set<AttributeType> required = new HashSet<AttributeType>(
+          ocToDelete.getRequiredAttributes());
+      Set<AttributeType> optional = new HashSet<AttributeType>(
+          ocToDelete.getOptionalAttributes());
+      if (required.contains(oldAttribute))
+      {
+        required.remove(oldAttribute);
+        required.add(newAttribute);
+      }
+      else if (optional.contains(oldAttribute))
+      {
+        optional.remove(oldAttribute);
+        optional.add(newAttribute);
+      }
+      ocToAdd = new ObjectClass("",
+          ocToDelete.getPrimaryName(),
+          allNames,
+          ocToDelete.getOID(),
+          ocToDelete.getDescription(),
+          ocToDelete.getSuperiorClass(),
+          required,
+          optional,
+          ocToDelete.getObjectClassType(),
+          ocToDelete.isObsolete(),
+          extraProperties);
+    }
+    else
+    {
+      // Nothing to be changed in the definition of the object class itself.
+      ocToAdd = ocToDelete;
+    }
+    return ocToAdd;
+  }
+
+  /**
+   * Updates the schema.
+   * @throws OpenDsException if an error occurs.
+   */
+  private void updateSchema() throws OpenDsException
+  {
+    Schema schema = getInfo().getServerDescriptor().getSchema();
+    ArrayList<AttributeType> attrs = new ArrayList<AttributeType>();
+    attrs.add(oldAttribute);
+    LinkedHashSet<AttributeType> attrsToDelete =
+      DeleteSchemaElementsTask.getOrderedAttributesToDelete(attrs, schema);
+    LinkedHashSet<ObjectClass> ocsToDelete =
+      DeleteSchemaElementsTask.getOrderedObjectClassesToDeleteFromAttrs(
+          attrsToDelete, schema);
+
+    LinkedHashSet<AttributeType> attrsToAdd =
+      new LinkedHashSet<AttributeType>();
+    ArrayList<AttributeType> lAttrsToDelete =
+      new ArrayList<AttributeType>(attrsToDelete);
+    for (int i = lAttrsToDelete.size() - 1; i >= 0; i--)
+    {
+      AttributeType attrToAdd = getAttributeToAdd(lAttrsToDelete.get(i));
+      if (attrToAdd != null)
+      {
+        attrsToAdd.add(attrToAdd);
+      }
+    }
+
+    ArrayList<ObjectClass> lOcsToDelete =
+      new ArrayList<ObjectClass>(ocsToDelete);
+    LinkedHashSet<ObjectClass> ocsToAdd = new LinkedHashSet<ObjectClass>();
+    for (int i = lOcsToDelete.size() - 1; i >= 0; i--)
+    {
+      ocsToAdd.add(getObjectClassToAdd(lOcsToDelete.get(i)));
+    }
+
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        getProgressDialog().appendProgressHtml(Utilities.applyFont(
+            INFO_CTRL_PANEL_EXPLANATION_TO_MODIFY_ATTRIBUTE.get(
+                oldAttribute.getNameOrOID())+"<br><br>",
+                ColorAndFontConstants.progressFont));
+      }
+    });
+
+    DeleteSchemaElementsTask deleteTask =
+      new DeleteSchemaElementsTask(getInfo(), getProgressDialog(), ocsToDelete,
+          attrsToDelete);
+    deleteTask.runTask();
+
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        getProgressDialog().appendProgressHtml(Utilities.applyFont("<br><br>",
+                ColorAndFontConstants.progressFont));
+      }
+    });
+
+    NewSchemaElementsTask createTask =
+      new NewSchemaElementsTask(getInfo(), getProgressDialog(), ocsToAdd,
+          attrsToAdd);
+    createTask.runTask();
+
+    notifyConfigurationElementCreated(newAttribute);
+  }
+}
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java
new file mode 100644
index 0000000..3a46366
--- /dev/null
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/ModifyObjectClassTask.java
@@ -0,0 +1,255 @@
+/*
+ * 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 2009 Sun Microsystems, Inc.
+ */
+package org.opends.guitools.controlpanel.task;
+
+import static org.opends.messages.AdminToolMessages.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.SwingUtilities;
+
+import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
+import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
+import org.opends.guitools.controlpanel.ui.ProgressDialog;
+import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.messages.Message;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.OpenDsException;
+import org.opends.server.types.Schema;
+
+/**
+ * The task that is in charge of modifying an object class definition (and all
+ * the references to this object class).
+ *
+ */
+public class ModifyObjectClassTask extends Task
+{
+  private ObjectClass oldObjectClass;
+  private ObjectClass newObjectClass;
+
+  /**
+   * The constructor of the task.
+   * @param info the control panel info.
+   * @param dlg the progress dialog that shows the progress of the task.
+   * @param oldObjectClass the old object class definition.
+   * @param newObjectClass the new object class definition.
+   */
+  public ModifyObjectClassTask(ControlPanelInfo info, ProgressDialog dlg,
+      ObjectClass oldObjectClass, ObjectClass newObjectClass)
+  {
+    super(info, dlg);
+    this.oldObjectClass = oldObjectClass;
+    this.newObjectClass = newObjectClass;
+    if (oldObjectClass == null)
+    {
+      throw new IllegalArgumentException("oldObjectClass cannot be null.");
+    }
+    if (newObjectClass == null)
+    {
+      throw new IllegalArgumentException("newObjectClass cannot be null.");
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Type getType()
+  {
+    return Type.MODIFY_SCHEMA_ELEMENT;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Message getTaskDescription()
+  {
+    return INFO_CTRL_PANEL_MODIFY_OBJECTCLASS_TASK_DESCRIPTION.get(
+        oldObjectClass.getNameOrOID());
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean canLaunch(Task taskToBeLaunched,
+      Collection<Message> incompatibilityReasons)
+  {
+    boolean canLaunch = true;
+    if (state == State.RUNNING &&
+        (taskToBeLaunched.getType() == Task.Type.DELETE_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.MODIFY_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.NEW_SCHEMA_ELEMENT))
+    {
+      incompatibilityReasons.add(getIncompatibilityMessage(this,
+            taskToBeLaunched));
+      canLaunch = false;
+    }
+    return canLaunch;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Set<String> getBackends()
+  {
+    return Collections.emptySet();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected List<String> getCommandLineArguments()
+  {
+    return Collections.emptyList();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getCommandLinePath()
+  {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void runTask()
+  {
+    try
+    {
+      updateSchema();
+      state = State.FINISHED_SUCCESSFULLY;
+    }
+    catch (Throwable t)
+    {
+      // TODO
+      //revertChanges();
+      lastException = t;
+      state = State.FINISHED_WITH_ERROR;
+    }
+  }
+
+
+  private ObjectClass getObjectClassToAdd(ObjectClass ocToDelete)
+  {
+    ObjectClass ocToAdd;
+    if (ocToDelete.equals(oldObjectClass))
+    {
+      ocToAdd = newObjectClass;
+    }
+    else if (oldObjectClass.equals(ocToDelete.getSuperiorClass()))
+    {
+      ArrayList<String> allNames = new ArrayList<String>();
+      for (String str : ocToDelete.getNormalizedNames())
+      {
+        allNames.add(str);
+      }
+      Map<String, List<String>> extraProperties =
+        DeleteSchemaElementsTask.cloneExtraProperties(ocToDelete);
+
+      ocToAdd = new ObjectClass("",
+          ocToDelete.getPrimaryName(),
+          allNames,
+          ocToDelete.getOID(),
+          ocToDelete.getDescription(),
+          newObjectClass,
+          ocToDelete.getRequiredAttributes(),
+          ocToDelete.getOptionalAttributes(),
+          ocToDelete.getObjectClassType(),
+          ocToDelete.isObsolete(),
+          extraProperties);
+    }
+    else
+    {
+      // Nothing to be changed in the definition of the object class itself.
+      ocToAdd = ocToDelete;
+    }
+    return ocToAdd;
+  }
+
+  /**
+   * Updates the schema.
+   * @throws OpenDsException if an error occurs.
+   */
+  private void updateSchema() throws OpenDsException
+  {
+    Schema schema = getInfo().getServerDescriptor().getSchema();
+    ArrayList<ObjectClass> ocs = new ArrayList<ObjectClass>();
+    ocs.add(oldObjectClass);
+    LinkedHashSet<ObjectClass> ocsToDelete =
+      DeleteSchemaElementsTask.getOrderedObjectClassesToDelete(ocs, schema);
+
+    ArrayList<ObjectClass> lOcsToDelete =
+      new ArrayList<ObjectClass>(ocsToDelete);
+    LinkedHashSet<ObjectClass> ocsToAdd = new LinkedHashSet<ObjectClass>();
+    for (int i = lOcsToDelete.size() - 1; i >= 0; i--)
+    {
+      ocsToAdd.add(getObjectClassToAdd(lOcsToDelete.get(i)));
+    }
+
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        getProgressDialog().appendProgressHtml(Utilities.applyFont(
+              INFO_CTRL_PANEL_EXPLANATION_TO_MODIFY_OBJECTCLASS.get(
+                  oldObjectClass.getNameOrOID())+"<br><br>",
+                  ColorAndFontConstants.progressFont));
+      }
+    });
+
+    DeleteSchemaElementsTask deleteTask =
+      new DeleteSchemaElementsTask(getInfo(), getProgressDialog(), ocsToDelete,
+          new LinkedHashSet<AttributeType>(0));
+    deleteTask.runTask();
+
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        getProgressDialog().appendProgressHtml(Utilities.applyFont("<br><br>",
+                ColorAndFontConstants.progressFont));
+      }
+    });
+
+    NewSchemaElementsTask createTask =
+      new NewSchemaElementsTask(getInfo(), getProgressDialog(), ocsToAdd,
+          new LinkedHashSet<AttributeType>(0));
+
+    createTask.runTask();
+
+    notifyConfigurationElementCreated(newObjectClass);
+  }
+}
+
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/NewSchemaElementsTask.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/NewSchemaElementsTask.java
new file mode 100644
index 0000000..fdc841e
--- /dev/null
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/NewSchemaElementsTask.java
@@ -0,0 +1,824 @@
+/*
+ * 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 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.guitools.controlpanel.task;
+
+import static org.opends.messages.AdminToolMessages.*;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.naming.NamingException;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.swing.SwingUtilities;
+
+import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
+import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
+import org.opends.guitools.controlpanel.ui.ProgressDialog;
+import org.opends.guitools.controlpanel.util.Utilities;
+import org.opends.messages.Message;
+import org.opends.quicksetup.util.Utils;
+import org.opends.server.config.ConfigConstants;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.CommonSchemaElements;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ExistingFileBehavior;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.Modification;
+import org.opends.server.types.ModificationType;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.OpenDsException;
+import org.opends.server.util.LDIFReader;
+import org.opends.server.util.LDIFWriter;
+import org.opends.server.util.ServerConstants;
+
+/**
+ * An abstract class used to re-factor some code between the different tasks
+ * that create elements in the schema.
+ *
+ */
+public class NewSchemaElementsTask extends Task
+{
+  LinkedHashSet<ObjectClass> ocsToAdd = new LinkedHashSet<ObjectClass>();
+  LinkedHashSet<AttributeType> attrsToAdd = new LinkedHashSet<AttributeType>();
+
+  /**
+   * Constructor of the task.
+   * @param info the control panel information.
+   * @param dlg the progress dialog where the task progress will be displayed.
+   * @param ocsToAdd the object classes that must be created in order.
+   * @param attrsToAdd the attributes that must be created in order.
+   */
+  public NewSchemaElementsTask(ControlPanelInfo info, ProgressDialog dlg,
+      LinkedHashSet<ObjectClass> ocsToAdd,
+      LinkedHashSet<AttributeType> attrsToAdd)
+  {
+    super(info, dlg);
+    this.ocsToAdd.addAll(ocsToAdd);
+    this.attrsToAdd.addAll(attrsToAdd);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Set<String> getBackends()
+  {
+    return Collections.emptySet();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean canLaunch(Task taskToBeLaunched,
+      Collection<Message> incompatibilityReasons)
+  {
+    boolean canLaunch = true;
+    if (state == State.RUNNING &&
+        (taskToBeLaunched.getType() == Task.Type.DELETE_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.MODIFY_SCHEMA_ELEMENT ||
+         taskToBeLaunched.getType() == Task.Type.NEW_SCHEMA_ELEMENT))
+    {
+      incompatibilityReasons.add(getIncompatibilityMessage(this,
+            taskToBeLaunched));
+      canLaunch = false;
+    }
+    return canLaunch;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void runTask()
+  {
+    state = State.RUNNING;
+    lastException = null;
+
+    try
+    {
+      updateSchema();
+      state = State.FINISHED_SUCCESSFULLY;
+    }
+    catch (Throwable t)
+    {
+      lastException = t;
+      state = State.FINISHED_WITH_ERROR;
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Type getType()
+  {
+    return Type.NEW_SCHEMA_ELEMENT;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Message getTaskDescription()
+  {
+    if (attrsToAdd.size() == 1 && ocsToAdd.isEmpty())
+    {
+      String attributeName = attrsToAdd.iterator().next().getNameOrOID();
+      return INFO_CTRL_PANEL_NEW_ATTRIBUTE_TASK_DESCRIPTION.get(attributeName);
+    }
+    else if (ocsToAdd.size() == 1 && attrsToAdd.isEmpty())
+    {
+      String ocName = ocsToAdd.iterator().next().getNameOrOID();
+      return INFO_CTRL_PANEL_NEW_OBJECTCLASS_TASK_DESCRIPTION.get(ocName);
+    }
+    else
+    {
+      ArrayList<String> attrNames = new ArrayList<String>();
+      for (AttributeType attribute : attrsToAdd)
+      {
+        attrNames.add(attribute.getNameOrOID());
+      }
+      ArrayList<String> ocNames = new ArrayList<String>();
+      for (ObjectClass oc : ocsToAdd)
+      {
+        ocNames.add(oc.getNameOrOID());
+      }
+      if (ocNames.isEmpty())
+      {
+        return INFO_CTRL_PANEL_NEW_ATTRIBUTES_TASK_DESCRIPTION.get(
+            Utils.getStringFromCollection(attrNames, ", "));
+      }
+      else if (attrNames.isEmpty())
+      {
+        return INFO_CTRL_PANEL_NEW_OBJECTCLASSES_TASK_DESCRIPTION.get(
+            Utils.getStringFromCollection(ocNames, ", "));
+      }
+      else
+      {
+        return INFO_CTRL_PANEL_NEW_SCHEMA_ELEMENTS_TASK_DESCRIPTION.get(
+            Utils.getStringFromCollection(attrNames, ", "),
+            Utils.getStringFromCollection(ocNames, ", "));
+      }
+    }
+  }
+
+  /**
+   * Update the schema.
+   * @throws OpenDsException if an error occurs.
+   */
+  private void updateSchema() throws OpenDsException
+  {
+    if (isServerRunning())
+    {
+      updateSchemaOnline();
+    }
+    else
+    {
+      updateSchemaOffline();
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getCommandLinePath()
+  {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected List<String> getCommandLineArguments()
+  {
+    return Collections.emptyList();
+  }
+
+  private void updateSchemaOnline() throws OpenDsException
+  {
+    // Add the schema elements one by one: we are not sure that the server
+    // will handle the adds sequentially if we only send one modification.
+    for (AttributeType attr : attrsToAdd)
+    {
+      addAttributeOnline(attr);
+      SwingUtilities.invokeLater(new Runnable()
+      {
+        public void run()
+        {
+          getProgressDialog().appendProgressHtml(Utilities.applyFont("<br><br>",
+              ColorAndFontConstants.progressFont));
+        }
+      });
+    }
+    for (ObjectClass oc : ocsToAdd)
+    {
+      addObjectClassOnline(oc);
+      SwingUtilities.invokeLater(new Runnable()
+      {
+        public void run()
+        {
+          getProgressDialog().appendProgressHtml(Utilities.applyFont("<br><br>",
+              ColorAndFontConstants.progressFont));
+        }
+      });
+    }
+  }
+
+  private void updateSchemaOffline() throws OpenDsException
+  {
+    // Group the changes in the same schema file.
+    LinkedHashMap<String, List<AttributeType>> hmAttrs =
+      new LinkedHashMap<String, List<AttributeType>>();
+    for (AttributeType attr : attrsToAdd)
+    {
+      String fileName = getFileName(attr);
+      if (fileName == null)
+      {
+        fileName = "";
+      }
+      List<AttributeType> attrs = hmAttrs.get(fileName);
+      if (attrs == null)
+      {
+        attrs = new ArrayList<AttributeType>();
+        hmAttrs.put(fileName, attrs);
+      }
+      attrs.add(attr);
+    }
+
+    LinkedHashMap<String, List<ObjectClass>> hmOcs =
+      new LinkedHashMap<String, List<ObjectClass>>();
+    for (ObjectClass oc : ocsToAdd)
+    {
+      String fileName = getFileName(oc);
+      if (fileName == null)
+      {
+        fileName = "";
+      }
+      List<ObjectClass> ocs = hmOcs.get(fileName);
+      if (ocs == null)
+      {
+        ocs = new ArrayList<ObjectClass>();
+        hmOcs.put(fileName, ocs);
+      }
+      ocs.add(oc);
+    }
+
+    LinkedHashSet<String> allFileNames = new LinkedHashSet<String>();
+    allFileNames.addAll(hmAttrs.keySet());
+    allFileNames.addAll(hmOcs.keySet());
+    for (String fileName : allFileNames)
+    {
+      List<AttributeType> attrs = hmAttrs.get(fileName);
+      List<ObjectClass> ocs = hmOcs.get(fileName);
+      if (attrs == null)
+      {
+        attrs = Collections.emptyList();
+      }
+      if (ocs == null)
+      {
+        ocs = Collections.emptyList();
+      }
+
+      if (fileName.equals(""))
+      {
+        fileName = null;
+      }
+      updateSchemaOffline(fileName, attrs, ocs);
+      SwingUtilities.invokeLater(new Runnable()
+      {
+        public void run()
+        {
+          getProgressDialog().appendProgressHtml(Utilities.applyFont("<br><br>",
+              ColorAndFontConstants.progressFont));
+        }
+      });
+    }
+  }
+
+  private void addAttributeOnline(final AttributeType attribute)
+  throws OpenDsException
+  {
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void run()
+      {
+        printEquivalentCommandLineToAddOnline(attribute);
+        getProgressDialog().appendProgressHtml(
+            Utilities.getProgressWithPoints(
+                INFO_CTRL_PANEL_CREATING_ATTRIBUTE_PROGRESS.get(
+                    attribute.getNameOrOID()),
+                    ColorAndFontConstants.progressFont));
+      }
+    });
+    try
+    {
+      BasicAttribute attr = new BasicAttribute(getAttributeName(attribute));
+      attr.add(getValueOnline(attribute));
+      ModificationItem mod = new ModificationItem(DirContext.ADD_ATTRIBUTE,
+          attr);
+      getInfo().getDirContext().modifyAttributes(
+          ConfigConstants.DN_DEFAULT_SCHEMA_ROOT,
+          new ModificationItem[]  { mod });
+    }
+    catch (NamingException ne)
+    {
+      throw new OnlineUpdateException(
+          ERR_CTRL_PANEL_ERROR_UPDATING_SCHEMA.get(ne.toString()), ne);
+    }
+    notifyConfigurationElementCreated(attribute);
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        getProgressDialog().appendProgressHtml(
+            Utilities.getProgressDone(ColorAndFontConstants.progressFont));
+      }
+    });
+  }
+
+  private void addObjectClassOnline(final ObjectClass objectClass)
+  throws OpenDsException
+  {
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void run()
+      {
+        printEquivalentCommandLineToAddOnline(objectClass);
+        getProgressDialog().appendProgressHtml(
+            Utilities.getProgressWithPoints(
+                INFO_CTRL_PANEL_CREATING_OBJECTCLASS_PROGRESS.get(
+                    objectClass.getNameOrOID()),
+                    ColorAndFontConstants.progressFont));
+      }
+    });
+    try
+    {
+      BasicAttribute attr = new BasicAttribute(getAttributeName(objectClass));
+      attr.add(getValueOnline(objectClass));
+      ModificationItem mod = new ModificationItem(DirContext.ADD_ATTRIBUTE,
+          attr);
+      getInfo().getDirContext().modifyAttributes(
+          ConfigConstants.DN_DEFAULT_SCHEMA_ROOT,
+          new ModificationItem[]  { mod });
+    }
+    catch (NamingException ne)
+    {
+      throw new OnlineUpdateException(
+          ERR_CTRL_PANEL_ERROR_UPDATING_SCHEMA.get(ne.toString()), ne);
+    }
+    notifyConfigurationElementCreated(objectClass);
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        getProgressDialog().appendProgressHtml(
+            Utilities.getProgressDone(ColorAndFontConstants.progressFont));
+      }
+    });
+  }
+
+  private String getValueOnline(CommonSchemaElements element)
+  {
+    return element.toString();
+  }
+
+  private String getValueOffline(CommonSchemaElements element)
+  {
+    Iterable<String> previousValues =
+      element.getExtraProperty(ServerConstants.SCHEMA_PROPERTY_FILENAME);
+    element.setExtraProperty(ServerConstants.SCHEMA_PROPERTY_FILENAME,
+        (String)null);
+    String attributeWithoutFileDefinition = element.toString();
+
+    if (previousValues != null)
+    {
+      ArrayList<String> vs = new ArrayList<String>();
+      for (String s : previousValues)
+      {
+        vs.add(s);
+      }
+      if (!vs.isEmpty())
+      {
+        element.setExtraProperty(ServerConstants.SCHEMA_PROPERTY_FILENAME, vs);
+      }
+    }
+    return attributeWithoutFileDefinition;
+  }
+
+  private void printEquivalentCommandLineToAddOnline(
+      CommonSchemaElements element)
+  {
+    ArrayList<String> args = new ArrayList<String>();
+    args.add("-a");
+    args.addAll(getObfuscatedCommandLineArguments(
+        getConnectionCommandLineArguments(true, true)));
+    args.add(getNoPropertiesFileArgument());
+
+    String equiv = getEquivalentCommandLine(getCommandLinePath("ldapmodify"),
+        args);
+
+    StringBuilder sb = new StringBuilder();
+    Message msg;
+    if (element instanceof AttributeType)
+    {
+      msg = INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_ATTRIBUTE_ONLINE.get(
+          element.getNameOrOID());
+    }
+    else
+    {
+      msg = INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_OBJECTCLASS_ONLINE.get(
+          element.getNameOrOID());
+    }
+    sb.append(msg+"<br><b>");
+    sb.append(equiv);
+    sb.append("<br>");
+    sb.append("dn: cn=schema<br>");
+    sb.append("changetype: modify<br>");
+    sb.append("add: "+getAttributeName(element)+"<br>");
+    sb.append(getAttributeName(element)+": "+getValueOnline(element));
+    sb.append("</b><br><br>");
+    getProgressDialog().appendProgressHtml(Utilities.applyFont(sb.toString(),
+        ColorAndFontConstants.progressFont));
+  }
+
+  private String getAttributeName(CommonSchemaElements element)
+  {
+    if (element instanceof AttributeType)
+    {
+      return ConfigConstants.ATTR_ATTRIBUTE_TYPES;
+    }
+    else
+    {
+      return ConfigConstants.ATTR_OBJECTCLASSES;
+    }
+  }
+
+  private String getFileName(CommonSchemaElements element)
+  {
+    String value = null;
+    Iterable<String> vs =
+      element.getExtraProperty(ServerConstants.SCHEMA_PROPERTY_FILENAME);
+    if (vs != null)
+    {
+      if (vs.iterator().hasNext())
+      {
+        value = vs.iterator().next();
+      }
+    }
+    return value;
+  }
+
+  private void updateSchemaOffline(String file,
+      final List<AttributeType> attributes,
+      final List<ObjectClass> objectClasses) throws OpenDsException
+  {
+    final boolean userSchema;
+    final String fileName;
+    if (file == null)
+    {
+      file = ConfigConstants.FILE_USER_SCHEMA_ELEMENTS;
+      userSchema = true;
+    }
+    else
+    {
+      userSchema = false;
+    }
+    File f = new File(file);
+    if (!f.isAbsolute())
+    {
+      f = new File(
+        DirectoryServer.getEnvironmentConfig().getSchemaDirectory(userSchema),
+        file);
+    }
+    fileName = f.getAbsolutePath();
+    final boolean isSchemaFileDefined = isSchemaFileDefined(fileName);
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void run()
+      {
+        printEquivalentCommandToAddOffline(fileName, isSchemaFileDefined,
+            attributes, objectClasses);
+        if (attributes.size() == 1 && objectClasses.isEmpty())
+        {
+          String attributeName = attributes.get(0).getNameOrOID();
+          getProgressDialog().appendProgressHtml(
+              Utilities.getProgressWithPoints(
+                  INFO_CTRL_PANEL_CREATING_ATTRIBUTE_PROGRESS.get(
+                      attributeName),
+                      ColorAndFontConstants.progressFont));
+        }
+        else if (objectClasses.size() == 1 && attributes.isEmpty())
+        {
+          String ocName = objectClasses.get(0).getNameOrOID();
+          getProgressDialog().appendProgressHtml(
+              Utilities.getProgressWithPoints(
+                  INFO_CTRL_PANEL_CREATING_OBJECTCLASS_PROGRESS.get(
+                      ocName),
+                      ColorAndFontConstants.progressFont));
+        }
+        else
+        {
+          getProgressDialog().appendProgressHtml(
+              Utilities.getProgressWithPoints(
+                  INFO_CTRL_PANEL_UPDATING_SCHEMA_FILE_PROGRESS.get(
+                      fileName),
+                      ColorAndFontConstants.progressFont));
+        }
+      }
+    });
+
+    updateSchemaFile(fileName, isSchemaFileDefined, attributes, objectClasses);
+
+    for (AttributeType attr : attributes)
+    {
+      notifyConfigurationElementCreated(attr);
+    }
+    for (ObjectClass oc : objectClasses)
+    {
+      notifyConfigurationElementCreated(oc);
+    }
+    SwingUtilities.invokeLater(new Runnable()
+    {
+      public void run()
+      {
+        getProgressDialog().appendProgressHtml(
+            Utilities.getProgressDone(ColorAndFontConstants.progressFont));
+      }
+    });
+  }
+
+  private void printEquivalentCommandToAddOffline(String schemaFile,
+      boolean isSchemaFileDefined,
+      List<AttributeType> attributes,
+      List<ObjectClass> objectClasses)
+  {
+    ArrayList<String> names = new ArrayList<String>();
+    for (AttributeType attr : attributes)
+    {
+      names.add(attr.getNameOrOID());
+    }
+    for (ObjectClass oc : objectClasses)
+    {
+      names.add(oc.getNameOrOID());
+    }
+    if (isSchemaFileDefined)
+    {
+      StringBuilder sb = new StringBuilder();
+      sb.append(
+          INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ELEMENT_OFFLINE.get(
+              Utils.getStringFromCollection(names, ", "),
+              schemaFile)+"<br><b>");
+      for (AttributeType attribute : attributes)
+      {
+        sb.append(
+            getAttributeName(attribute)+": "+getValueOffline(attribute)+"<br>");
+      }
+      for (ObjectClass oc : objectClasses)
+      {
+        sb.append(getAttributeName(oc)+": "+getValueOffline(oc)+"<br>");
+      }
+      sb.append("</b><br><br>");
+
+      getProgressDialog().appendProgressHtml(Utilities.applyFont(sb.toString(),
+          ColorAndFontConstants.progressFont));
+    }
+    else
+    {
+      StringBuilder sb = new StringBuilder();
+      sb.append(INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ENTRY_OFFLINE.get(
+          Utils.getStringFromCollection(names, ", "),
+              schemaFile)+"<br><b>");
+      for (String line : getSchemaEntryLines())
+      {
+        sb.append(line);
+        sb.append("<br>");
+      }
+      for (AttributeType attribute : attributes)
+      {
+        sb.append(
+            getAttributeName(attribute)+": "+getValueOffline(attribute)+"<br>");
+      }
+      for (ObjectClass oc : objectClasses)
+      {
+        sb.append(getAttributeName(oc)+": "+getValueOffline(oc)+"<br>");
+      }
+      sb.append("</b><br><br>");
+      getProgressDialog().appendProgressHtml(Utilities.applyFont(sb.toString(),
+          ColorAndFontConstants.progressFont));
+    }
+  }
+
+  /**
+   * Returns whether the file defined in the schema element exists or not.
+   * @param the path to the schema file.
+   * @return <CODE>true</CODE> if the schema file is defined and
+   * <CODE>false</CODE> otherwise.
+   */
+  private boolean isSchemaFileDefined(String schemaFile)
+  {
+    boolean schemaDefined = false;
+    LDIFReader reader = null;
+    try
+    {
+      reader = new LDIFReader(new LDIFImportConfig(schemaFile));
+      Entry entry = reader.readEntry();
+      if (entry != null)
+      {
+        schemaDefined = true;
+      }
+    }
+    catch (Throwable t)
+    {
+    }
+    finally
+    {
+      if (reader != null)
+      {
+        try
+        {
+          reader.close();
+        }
+        catch (Throwable t)
+        {
+        }
+      }
+    }
+    return schemaDefined;
+  }
+
+  /**
+   * Returns the list of LDIF lines that are enough to create the entry
+   * containing only the schema element associated with this task.
+   * @return the list of LDIF lines that are enough to create the entry
+   * containing only the schema element associated with this task.
+   */
+  private ArrayList<String> getSchemaEntryLines()
+  {
+    ArrayList<String> lines = new ArrayList<String>();
+    lines.add("dn: cn=schema");
+    lines.add("objectClass: top");
+    lines.add("objectClass: ldapSubentry");
+    lines.add("objectClass: subschema");
+    return lines;
+  }
+
+
+  /**
+   * Updates the contents of the schema file.
+   *
+   * @param schemaFile the schema file.
+   * @param isSchemaFileDefined whether the schema is defined or not.
+   * @param attributes the attributes to add.
+   * @param objectClasses the object classes to add.
+   * @throws OpenDsException if an error occurs updating the schema file.
+   */
+  private void updateSchemaFile(String schemaFile,
+      boolean isSchemaFileDefined,
+      List<AttributeType> attributes,
+      List<ObjectClass> objectClasses) throws OpenDsException
+  {
+    if (isSchemaFileDefined)
+    {
+      LDIFExportConfig exportConfig =
+        new LDIFExportConfig(schemaFile,
+                             ExistingFileBehavior.OVERWRITE);
+      LDIFReader reader = null;
+      Entry schemaEntry = null;
+      try
+      {
+        reader = new LDIFReader(new LDIFImportConfig(schemaFile));
+        schemaEntry = reader.readEntry();
+
+        for (AttributeType attribute : attributes)
+        {
+          Modification mod = new Modification(ModificationType.ADD,
+              Attributes.create(getAttributeName(attribute).toLowerCase(),
+                  getValueOffline(attribute)));
+          schemaEntry.applyModification(mod);
+        }
+        for (ObjectClass oc : objectClasses)
+        {
+          Modification mod = new Modification(ModificationType.ADD,
+              Attributes.create(getAttributeName(oc).toLowerCase(),
+                  getValueOffline(oc)));
+          schemaEntry.applyModification(mod);
+        }
+        LDIFWriter writer = new LDIFWriter(exportConfig);
+        writer.writeEntry(schemaEntry);
+        exportConfig.getWriter().newLine();
+      }
+      catch (Throwable t)
+      {
+      }
+      finally
+      {
+        if (reader != null)
+        {
+          try
+          {
+            reader.close();
+          }
+          catch (Throwable t)
+          {
+          }
+        }
+        if (exportConfig != null)
+        {
+          try
+          {
+            exportConfig.close();
+          }
+          catch (Throwable t)
+          {
+          }
+        }
+      }
+    }
+    else
+    {
+      LDIFExportConfig exportConfig =
+        new LDIFExportConfig(schemaFile,
+                             ExistingFileBehavior.FAIL);
+      try
+      {
+        ArrayList<String> lines = getSchemaEntryLines();
+        for (AttributeType attribute : attributes)
+        {
+          lines.add(
+              getAttributeName(attribute)+": "+getValueOffline(attribute));
+        }
+        for (ObjectClass oc : objectClasses)
+        {
+          lines.add(getAttributeName(oc)+": "+getValueOffline(oc));
+        }
+        for (String line : lines)
+        {
+          LDIFWriter.writeLDIFLine(new StringBuilder(line),
+              exportConfig.getWriter(), exportConfig.getWrapColumn() > 1,
+              exportConfig.getWrapColumn());
+        }
+
+        exportConfig.getWriter().newLine();
+      }
+      catch (Throwable t)
+      {
+        throw new OfflineUpdateException(
+            ERR_CTRL_PANEL_ERROR_UPDATING_SCHEMA.get(t.toString()), t);
+      }
+      finally
+      {
+        if (exportConfig != null)
+        {
+          try
+          {
+            exportConfig.close();
+          }
+          catch (Throwable t)
+          {
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/SchemaTask.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/SchemaTask.java
deleted file mode 100644
index 67e0fe5..0000000
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/SchemaTask.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * 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 2008-2009 Sun Microsystems, Inc.
- */
-
-package org.opends.guitools.controlpanel.task;
-
-import static org.opends.messages.AdminToolMessages.*;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
-import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
-import org.opends.guitools.controlpanel.ui.ProgressDialog;
-import org.opends.guitools.controlpanel.util.Utilities;
-import org.opends.messages.Message;
-import org.opends.server.config.ConfigConstants;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.CommonSchemaElements;
-import org.opends.server.types.LDIFImportConfig;
-import org.opends.server.types.OpenDsException;
-import org.opends.server.util.LDIFReader;
-
-/**
- * An abstract class used to re-factor some code between the different tasks
- * that update the schema.
- *
- */
-public abstract class SchemaTask extends Task
-{
-  private Set<String> backendSet;
-  /**
-   * The file where the schema elements updated by this task is located.
-   */
-  protected String schemaFile;
-
-  /**
-   * Whether the schema file is defined or not.
-   */
-  protected boolean isSchemaFileDefined;
-
-  /**
-   * Constructor of the task.
-   * @param info the control panel information.
-   * @param dlg the progress dialog where the task progress will be displayed.
-   */
-  protected SchemaTask(ControlPanelInfo info, ProgressDialog dlg)
-  {
-    super(info, dlg);
-    backendSet = new HashSet<String>();
-    CommonSchemaElements element = getSchemaElement();
-    schemaFile = element.getSchemaFile();
-    boolean userSchema = false ;
-    if (schemaFile == null)
-    {
-      schemaFile = ConfigConstants.FILE_USER_SCHEMA_ELEMENTS;
-      userSchema = true;
-    }
-    File f = new File(schemaFile);
-    if (!f.isAbsolute())
-    {
-      f = new File(
-        DirectoryServer.getEnvironmentConfig().getSchemaDirectory(userSchema),
-        schemaFile);
-    }
-    schemaFile = f.getAbsolutePath();
-    isSchemaFileDefined = isSchemaFileDefined();
-  }
-
-  /**
-   * Returns the schema element that this task is handling.
-   * @return the schema element that this task is handling.
-   */
-  protected abstract CommonSchemaElements getSchemaElement();
-
-  /**
-   * {@inheritDoc}
-   */
-  public Set<String> getBackends()
-  {
-    return backendSet;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean canLaunch(Task taskToBeLaunched,
-      Collection<Message> incompatibilityReasons)
-  {
-    boolean canLaunch = true;
-    return canLaunch;
-  }
-
-  /**
-   * Returns whether the file defined in the schema element exists or not.
-   * @return <CODE>true</CODE> if the schema file is defined and
-   * <CODE>false</CODE> otherwise.
-   */
-  protected boolean isSchemaFileDefined()
-  {
-    boolean schemaDefined = false;
-    LDIFReader reader = null;
-    try
-    {
-      reader = new LDIFReader(new LDIFImportConfig(schemaFile));
-      while (reader.readEntry() != null)
-      {
-        schemaDefined = true;
-        break;
-      }
-    }
-    catch (Throwable t)
-    {
-    }
-    finally
-    {
-      if (reader != null)
-      {
-        try
-        {
-          reader.close();
-        }
-        catch (Throwable t)
-        {
-        }
-      }
-    }
-    return schemaDefined;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public void runTask()
-  {
-    state = State.RUNNING;
-    lastException = null;
-
-    try
-    {
-      updateSchema();
-      state = State.FINISHED_SUCCESSFULLY;
-    }
-    catch (Throwable t)
-    {
-      lastException = t;
-      state = State.FINISHED_WITH_ERROR;
-    }
-  }
-
-  /**
-   * Update the schema.
-   * @throws OpenDsException if an error occurs.
-   */
-  protected abstract void updateSchema() throws OpenDsException;
-
-  /**
-   * {@inheritDoc}
-   */
-  protected String getCommandLinePath()
-  {
-    return null;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  protected ArrayList<String> getCommandLineArguments()
-  {
-    return new ArrayList<String>();
-  }
-
-  /**
-   * Returns the list of LDIF lines that are enough to create the entry
-   * containing only the schema element associated with this task.
-   * @return the list of LDIF lines that are enough to create the entry
-   * containing only the schema element associated with this task.
-   */
-  protected ArrayList<String> getSchemaEntryLines()
-  {
-    ArrayList<String> lines = new ArrayList<String>();
-    lines.add("dn: cn=schema");
-    lines.add("objectClass: top");
-    lines.add("objectClass: ldapSubentry");
-    lines.add("objectClass: subschema");
-    lines.add(getSchemaFileAttributeName()+": "+
-        getSchemaFileAttributeValue());
-    return lines;
-  }
-
-  /**
-   * Returns the attribute in the schema file that contains the definition
-   * of the schema element.
-   * @return the attribute in the schema file that contains the definition
-   * of the schema element.
-   */
-  protected abstract String getSchemaFileAttributeName();
-
-  /**
-   * Returns the value in the schema file that corresponds to the definition
-   * of the schema element.
-   * @return the value in the schema file that corresponds to the definition
-   * of the schema element.
-   */
-  protected abstract String getSchemaFileAttributeValue();
-
-
-  /**
-   * Prints the equivalent command-line to add the schema element.
-   *
-   */
-  protected void printEquivalentCommandToAdd()
-  {
-    if (!isServerRunning())
-    {
-      if (isSchemaFileDefined)
-      {
-        getProgressDialog().appendProgressHtml(Utilities.applyFont(
-            INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ELEMENT_OFFLINE.get(
-                schemaFile)+"<br><b>"+
-            getSchemaFileAttributeName()+": "+getSchemaFileAttributeValue()+
-            "</b><br><br>",
-            ColorAndFontConstants.progressFont));
-      }
-      else
-      {
-        StringBuilder sb = new StringBuilder();
-        for (String line : getSchemaEntryLines())
-        {
-          if (sb.length() > 0)
-          {
-            sb.append("<br>");
-          }
-          sb.append(line);
-        }
-        getProgressDialog().appendProgressHtml(Utilities.applyFont(
-            INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ENTRY_OFFLINE.get(
-                schemaFile)+"<br><b>"+sb+"</b><br><br>",
-            ColorAndFontConstants.progressFont));
-      }
-    }
-    else
-    {
-      ArrayList<String> args = new ArrayList<String>();
-      args.add("-a");
-      args.addAll(getObfuscatedCommandLineArguments(
-          getConnectionCommandLineArguments(true, true)));
-      args.add(getNoPropertiesFileArgument());
-
-      String equiv = getEquivalentCommandLine(getCommandLinePath("ldapmodify"),
-          args);
-
-      StringBuilder sb = new StringBuilder();
-      sb.append(
-          INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ELEMENT_ONLINE.get()+
-          "<br><b>");
-      sb.append(equiv);
-      sb.append("<br>");
-      sb.append("dn: cn=schema<br>");
-      sb.append("changetype: modify<br>");
-      sb.append("add: "+getSchemaFileAttributeName()+"<br>");
-      sb.append(getSchemaFileAttributeName()+": "+
-          getSchemaFileAttributeValue());
-      sb.append("</b><br><br>");
-      getProgressDialog().appendProgressHtml(Utilities.applyFont(sb.toString(),
-          ColorAndFontConstants.progressFont));
-    }
-  }
-}
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/Task.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/Task.java
index e913a3d..ebf75e6 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/Task.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/Task.java
@@ -45,6 +45,9 @@
 import org.opends.admin.ads.util.ConnectionUtils;
 import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
 import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
+import org.opends.guitools.controlpanel.event.ConfigurationElementCreatedEvent;
+import org.opends.guitools.controlpanel.event.
+ ConfigurationElementCreatedListener;
 import org.opends.guitools.controlpanel.event.PrintStreamListener;
 import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
 import org.opends.guitools.controlpanel.ui.ProgressDialog;
@@ -150,21 +153,17 @@
      */
     JAVA_SETTINGS_UPDATE,
     /**
-     * Creating a new attribute in the schema.
+     * Creating a new element in the schema.
      */
-    NEW_ATTRIBUTE,
+    NEW_SCHEMA_ELEMENT,
     /**
-     * Creating a new objectclass in the schema.
+     * Deleting an schema element.
      */
-    NEW_OBJECTCLASS,
+    DELETE_SCHEMA_ELEMENT,
     /**
-     * Deleting an attribute in the schema.
+     * Modify an schema element.
      */
-    DELETE_ATTRIBUTE,
-    /**
-     * Deleting an objectclass in the schema.
-     */
-    DELETE_OBJECTCLASS,
+    MODIFY_SCHEMA_ELEMENT,
     /**
      * Modifying an entry.
      */
@@ -269,6 +268,9 @@
 
   private ProgressDialog progressDialog;
 
+  private ArrayList<ConfigurationElementCreatedListener> confListeners =
+    new ArrayList<ConfigurationElementCreatedListener>();
+
   private static int MAX_BINARY_LENGTH_TO_DISPLAY = 1024;
 
   /**
@@ -424,6 +426,40 @@
   public abstract Message getTaskDescription();
 
   /**
+   * Adds a configuration element created listener.
+   * @param listener the listener.
+   */
+  public void addConfigurationElementCreatedListener(
+      ConfigurationElementCreatedListener listener)
+  {
+    confListeners.add(listener);
+  }
+
+  /**
+   * Removes a configuration element created listener.
+   * @param listener the listener.
+   */
+  public void removeConfigurationElementCreatedListener(
+      ConfigurationElementCreatedListener listener)
+  {
+    confListeners.remove(listener);
+  }
+
+  /**
+   * Notifies the configuration element created listener that a new object has
+   * been created.
+   * @param configObject the created object.
+   */
+  protected void notifyConfigurationElementCreated(Object configObject)
+  {
+    for (ConfigurationElementCreatedListener listener : confListeners)
+    {
+      listener.elementCreated(
+          new ConfigurationElementCreatedEvent(this, configObject));
+    }
+  }
+
+  /**
    * Returns a String representation of a value.  In general this is called
    * to display the command-line equivalent when we do a modification in an
    * entry.  But since some attributes must be obfuscated (like the user
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
index 6b4aa72..d19b798 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseSchemaPanel.java
@@ -44,6 +44,7 @@
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -86,6 +87,7 @@
 import org.opends.guitools.controlpanel.util.Utilities;
 import org.opends.guitools.controlpanel.util.ViewPositions;
 import org.opends.messages.Message;
+import org.opends.messages.MessageBuilder;
 import org.opends.server.api.AttributeSyntax;
 import org.opends.server.api.MatchingRule;
 import org.opends.server.types.AttributeType;
@@ -518,6 +520,14 @@
         selectElementUnder(root, element, model);
       }
     });
+    entryPane.addConfigurationElementCreatedListener(
+        new ConfigurationElementCreatedListener()
+        {
+          public void elementCreated(ConfigurationElementCreatedEvent ev)
+          {
+            configurationElementCreated(ev);
+          }
+        });
 
     treePane.getTree().addTreeSelectionListener(new TreeSelectionListener()
     {
@@ -632,32 +642,49 @@
   {
     final ServerDescriptor desc = ev.getNewDescriptor();
     final boolean forceScroll = lastSchema == null;
-    if ((lastSchema == null) ||
-        !ServerDescriptor.areSchemasEqual(lastSchema, desc.getSchema())||
-        true)
+    Schema schema = desc.getSchema();
+    boolean schemaChanged;
+    if (schema != null && lastSchema != null)
     {
-      lastSchema = desc.getSchema();
-      if (lastSchema != null)
+      schemaChanged = !ServerDescriptor.areSchemasEqual(lastSchema, schema);
+    }
+    else if (schema == null && lastSchema != null)
+    {
+      schemaChanged = false;
+    }
+    else if (lastSchema == null && schema != null)
+    {
+      schemaChanged = true;
+    }
+    else
+    {
+      schemaChanged = false;
+    }
+    if (schemaChanged)
+    {
+      lastSchema = schema;
+      SwingUtilities.invokeLater(new Runnable()
       {
-        SwingUtilities.invokeLater(new Runnable()
+        public void run()
         {
-          public void run()
+          repopulateTree(treePane.getTree(), forceScroll);
+          if (errorPane.isVisible())
           {
-            repopulateTree(treePane.getTree(), forceScroll);
+            errorPane.setVisible(false);
           }
-        });
-      }
-      else
-      {
-        updateErrorPane(errorPane,
-            ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
-            ColorAndFontConstants.errorTitleFont,
-            ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get(),
-            ColorAndFontConstants.defaultFont);
-        if (!errorPane.isVisible())
-        {
-          errorPane.setVisible(true);
         }
+      });
+    }
+    else if (lastSchema == null)
+    {
+      updateErrorPane(errorPane,
+          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
+          ColorAndFontConstants.errorTitleFont,
+          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get(),
+          ColorAndFontConstants.defaultFont);
+      if (!errorPane.isVisible())
+      {
+        errorPane.setVisible(true);
       }
     }
   }
@@ -1099,8 +1126,8 @@
       }
       else if (node instanceof CustomObjectClassTreeNode)
       {
-        entryPane.updateCustomObjectClass(
-            ((CustomObjectClassTreeNode)node).getObjectClass(), lastSchema);
+        ObjectClass oc = ((CustomObjectClassTreeNode)node).getObjectClass();
+        entryPane.updateCustomObjectClass(oc, lastSchema);
       }
       else if (node instanceof StandardAttributeTreeNode)
       {
@@ -1114,8 +1141,8 @@
       }
       else if (node instanceof CustomAttributeTreeNode)
       {
-        entryPane.updateCustomAttribute(
-            ((CustomAttributeTreeNode)node).getAttribute(), lastSchema);
+        AttributeType attr = ((CustomAttributeTreeNode)node).getAttribute();
+        entryPane.updateCustomAttribute(attr, lastSchema);
       }
       else if (node instanceof MatchingRuleTreeNode)
       {
@@ -1248,146 +1275,20 @@
     }
 
     Schema schema = getInfo().getServerDescriptor().getSchema();
-    ArrayList<String> ocNames = new ArrayList<String>();
-    ArrayList<String> attrNames = new ArrayList<String>();
-    if (schema != null)
-    {
-//    Analyze objectClasses
-      for (ObjectClass objectClass : ocsToDelete)
-      {
-        ArrayList<ObjectClass> childClasses = new ArrayList<ObjectClass>();
-        for (ObjectClass o : schema.getObjectClasses().values())
-        {
-          if (objectClass.equals(o.getSuperiorClass()))
-          {
-            childClasses.add(o);
-          }
-        }
-        childClasses.removeAll(ocsToDelete);
-        if (!childClasses.isEmpty())
-        {
-          ArrayList<String> childNames = new ArrayList<String>();
-          for (ObjectClass oc : childClasses)
-          {
-            childNames.add(oc.getNameOrOID());
-          }
-          String ocName = objectClass.getNameOrOID();
-          errors.add(ERR_CANNOT_DELETE_PARENT_OBJECTCLASS.get(ocName,
-              Utilities.getStringFromCollection(childNames, ", "), ocName));
-        }
-        ocNames.add(objectClass.getNameOrOID());
-      }
-//    Analyze attributes
-      for (AttributeType attribute : attrsToDelete)
-      {
-        String attrName = attribute.getNameOrOID();
-        ArrayList<AttributeType> childAttributes =
-          new ArrayList<AttributeType>();
-        for (AttributeType attr : schema.getAttributeTypes().values())
-        {
-          if (attribute.equals(attr.getSuperiorType()))
-          {
-            childAttributes.add(attr);
-          }
-        }
-        childAttributes.removeAll(attrsToDelete);
-        if (!childAttributes.isEmpty())
-        {
-          ArrayList<String> childNames = new ArrayList<String>();
-          for (AttributeType attr : childAttributes)
-          {
-            childNames.add(attr.getNameOrOID());
-          }
-          errors.add(ERR_CANNOT_DELETE_PARENT_ATTRIBUTE.get(attrName,
-              Utilities.getStringFromCollection(childNames, ", "), attrName));
-        }
-
-        ArrayList<String> dependentClasses = new ArrayList<String>();
-        for (ObjectClass o : schema.getObjectClasses().values())
-        {
-          if (o.getRequiredAttributeChain().contains(attribute))
-          {
-            dependentClasses.add(o.getNameOrOID());
-          }
-        }
-        dependentClasses.removeAll(ocsToDelete);
-        if (!dependentClasses.isEmpty())
-        {
-          errors.add(ERR_CANNOT_DELETE_ATTRIBUTE_WITH_DEPENDENCIES.get(
-              attrName,
-              Utilities.getStringFromCollection(dependentClasses, ", "),
-              attrName));
-        }
-        attrNames.add(attribute.getNameOrOID());
-      }
-    }
-    else
+    if (schema == null)
     {
       errors.add(ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get());
     }
     if (errors.isEmpty())
     {
-      // Reorder objectClasses and attributes to delete them in the proper
-      // order.
-      ArrayList<ObjectClass> orderedObjectClasses =
-        new ArrayList<ObjectClass>();
-      for (ObjectClass oc : ocsToDelete)
-      {
-        int index = -1;
-        for (int i=0; i<orderedObjectClasses.size(); i++)
-        {
-          ObjectClass parent = orderedObjectClasses.get(i).getSuperiorClass();
-          while ((parent != null) && (index == -1))
-          {
-            if (parent.equals(oc))
-            {
-              index = i+1;
-            }
-            else
-            {
-              parent = parent.getSuperiorClass();
-            }
-          }
-        }
-        if (index == -1)
-        {
-          orderedObjectClasses.add(oc);
-        }
-        else
-        {
-          orderedObjectClasses.add(index, oc);
-        }
-      }
+      Message confirmationMessage =
+        getConfirmationMessage(ocsToDelete, attrsToDelete, schema);
 
-      ArrayList<AttributeType> orderedAttributes =
-        new ArrayList<AttributeType>();
-      for (AttributeType attr : attrsToDelete)
-      {
-        int index = -1;
-        for (int i=0; i<orderedAttributes.size(); i++)
-        {
-          AttributeType parent = orderedAttributes.get(i).getSuperiorType();
-          while ((parent != null) && (index == -1))
-          {
-            if (parent.equals(attr))
-            {
-              index = i+1;
-            }
-            else
-            {
-              parent = parent.getSuperiorType();
-            }
-          }
-        }
-        if (index == -1)
-        {
-          orderedAttributes.add(attr);
-        }
-        else
-        {
-          orderedAttributes.add(index, attr);
-        }
-      }
+      LinkedHashSet<AttributeType> orderedAttributes =
+        getOrderedAttributesToDelete(attrsToDelete);
+      LinkedHashSet<ObjectClass> orderedObjectClasses =
+        getOrderedObjectClassesToDelete(ocsToDelete);
+
       Message title;
       if (orderedAttributes.isEmpty())
       {
@@ -1414,11 +1315,6 @@
       if (errors.isEmpty())
       {
         ArrayList<String> allNames = new ArrayList<String>();
-        allNames.addAll(ocNames);
-        allNames.addAll(attrNames);
-        Message confirmationMessage =
-          INFO_CTRL_PANEL_CONFIRMATION_DELETE_SCHEMA_ELEMENTS_DETAILS.get(
-          Utilities.getStringFromCollection(allNames, ", "));
         if (displayConfirmationDialog(
             INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
             confirmationMessage))
@@ -1474,7 +1370,7 @@
    * do the filtering based on the name.
    * @param oc the object class.
    * @param ocName the name provided by the user.
-   * @return <CODE>true</CODE> if the objectclass must be added and
+   * @return <CODE>true</CODE> if the object class must be added and
    * <CODE>false</CODE> otherwise.
    */
   private boolean mustAddObjectClassName(ObjectClass oc, String ocName)
@@ -1749,11 +1645,7 @@
           {
             public void elementCreated(ConfigurationElementCreatedEvent ev)
             {
-              Object o = ev.getConfigurationObject();
-              if (o instanceof CommonSchemaElements)
-              {
-                lastCreatedElement = (CommonSchemaElements)o;
-              }
+              configurationElementCreated(ev);
             }
           });
     }
@@ -1775,17 +1667,22 @@
           {
             public void elementCreated(ConfigurationElementCreatedEvent ev)
             {
-              Object o = ev.getConfigurationObject();
-              if (o instanceof CommonSchemaElements)
-              {
-                lastCreatedElement = (CommonSchemaElements)o;
-              }
+              configurationElementCreated(ev);
             }
           });
     }
     newObjectClassDialog.setVisible(true);
   }
 
+  private void configurationElementCreated(ConfigurationElementCreatedEvent ev)
+  {
+    Object o = ev.getConfigurationObject();
+    if (o instanceof CommonSchemaElements)
+    {
+      lastCreatedElement = (CommonSchemaElements)o;
+    }
+  }
+
   private HashMap<Object, ImageIcon> hmCategoryImages =
     new HashMap<Object, ImageIcon>();
   private HashMap<Class<?>, ImageIcon> hmImages =
@@ -1850,4 +1747,198 @@
       return icon;
     }
   }
+
+  private LinkedHashSet<ObjectClass> getOrderedObjectClassesToDelete(
+      Collection<ObjectClass> ocsToDelete)
+  {
+    ArrayList<ObjectClass> lOrderedOcs = new ArrayList<ObjectClass>();
+    // Reorder objectClasses and attributes to delete them in the proper
+    // order.
+    for (ObjectClass oc : ocsToDelete)
+    {
+      int index = -1;
+      for (int i=0; i<lOrderedOcs.size(); i++)
+      {
+        ObjectClass parent = lOrderedOcs.get(i).getSuperiorClass();
+        while ((parent != null) && (index == -1))
+        {
+          if (parent.equals(oc))
+          {
+            index = i+1;
+          }
+          else
+          {
+            parent = parent.getSuperiorClass();
+          }
+        }
+      }
+      if (index == -1)
+      {
+        lOrderedOcs.add(oc);
+      }
+      else
+      {
+        lOrderedOcs.add(index, oc);
+      }
+    }
+    return new LinkedHashSet<ObjectClass>(lOrderedOcs);
+  }
+
+  private LinkedHashSet<AttributeType> getOrderedAttributesToDelete(
+      Collection<AttributeType> attrsToDelete)
+  {
+    ArrayList<AttributeType> lOrderedAttributes =
+      new ArrayList<AttributeType>();
+    for (AttributeType attr : attrsToDelete)
+    {
+      int index = -1;
+      for (int i=0; i<lOrderedAttributes.size(); i++)
+      {
+        AttributeType parent = lOrderedAttributes.get(i).getSuperiorType();
+        while ((parent != null) && (index == -1))
+        {
+          if (parent.equals(attr))
+          {
+            index = i+1;
+          }
+          else
+          {
+            parent = parent.getSuperiorType();
+          }
+        }
+      }
+      if (index == -1)
+      {
+        lOrderedAttributes.add(attr);
+      }
+      else
+      {
+        lOrderedAttributes.add(index, attr);
+      }
+    }
+    return new LinkedHashSet<AttributeType>(lOrderedAttributes);
+  }
+
+  private Message getConfirmationMessage(
+      Collection<ObjectClass> ocsToDelete,
+      Collection<AttributeType> attrsToDelete,
+      Schema schema)
+  {
+    ArrayList<ObjectClass> childClasses = new ArrayList<ObjectClass>();
+    // Analyze objectClasses
+    for (ObjectClass objectClass : ocsToDelete)
+    {
+      for (ObjectClass o : schema.getObjectClasses().values())
+      {
+        if (objectClass.equals(o.getSuperiorClass()))
+        {
+          childClasses.add(o);
+        }
+      }
+      childClasses.removeAll(ocsToDelete);
+    }
+
+    ArrayList<AttributeType> childAttributes = new ArrayList<AttributeType>();
+    TreeSet<String> dependentClasses = new TreeSet<String>();
+    // Analyze attributes
+    for (AttributeType attribute : attrsToDelete)
+    {
+      for (AttributeType attr : schema.getAttributeTypes().values())
+      {
+        if (attribute.equals(attr.getSuperiorType()))
+        {
+          childAttributes.add(attr);
+        }
+      }
+      childAttributes.removeAll(attrsToDelete);
+
+      for (ObjectClass o : schema.getObjectClasses().values())
+      {
+        if (o.getRequiredAttributeChain().contains(attribute))
+        {
+          dependentClasses.add(o.getNameOrOID());
+        }
+        else if (o.getOptionalAttributeChain().contains(attribute))
+        {
+          dependentClasses.add(o.getNameOrOID());
+        }
+      }
+      for (ObjectClass oc : ocsToDelete)
+      {
+        dependentClasses.remove(oc.getNameOrOID());
+      }
+    }
+
+    MessageBuilder mb = new MessageBuilder();
+    if (!childClasses.isEmpty())
+    {
+      TreeSet<String> childNames = new TreeSet<String>();
+      for (ObjectClass oc : childClasses)
+      {
+        childNames.add(oc.getNameOrOID());
+      }
+      if (ocsToDelete.size() == 1)
+      {
+        mb.append(INFO_OBJECTCLASS_IS_SUPERIOR.get(
+            ocsToDelete.iterator().next().getNameOrOID(),
+            Utilities.getStringFromCollection(childNames, ", ")));
+      }
+      else
+      {
+        mb.append(INFO_OBJECTCLASSES_ARE_SUPERIOR.get(
+            Utilities.getStringFromCollection(childNames, ", ")));
+      }
+      mb.append("<br>");
+    }
+    if (!childAttributes.isEmpty())
+    {
+      TreeSet<String> childNames = new TreeSet<String>();
+      for (AttributeType attr : childAttributes)
+      {
+        childNames.add(attr.getNameOrOID());
+      }
+      if (attrsToDelete.size() == 1)
+      {
+        mb.append(INFO_ATTRIBUTE_IS_SUPERIOR.get(
+            attrsToDelete.iterator().next().getNameOrOID(),
+            Utilities.getStringFromCollection(childNames, ", ")));
+      }
+      else
+      {
+        mb.append(INFO_ATTRIBUTES_ARE_SUPERIOR.get(
+            Utilities.getStringFromCollection(childNames, ", ")));
+      }
+      mb.append("<br>");
+    }
+    if (!dependentClasses.isEmpty())
+    {
+      if (attrsToDelete.size() == 1)
+      {
+        mb.append(INFO_ATTRIBUTE_WITH_DEPENDENCIES.get(
+            attrsToDelete.iterator().next().getNameOrOID(),
+            Utilities.getStringFromCollection(dependentClasses, ", ")));
+      }
+      else
+      {
+        mb.append(INFO_ATTRIBUTES_WITH_DEPENDENCIES.get(
+            Utilities.getStringFromCollection(dependentClasses, ", ")));
+      }
+      mb.append("<br>");
+    }
+
+    ArrayList<String> allNames = new ArrayList<String>();
+    for (ObjectClass ocToDelete : ocsToDelete)
+    {
+      allNames.add(ocToDelete.getNameOrOID());
+    }
+    for (AttributeType attrToDelete : attrsToDelete)
+    {
+      allNames.add(attrToDelete.getNameOrOID());
+    }
+    Message confirmationMessage =
+      INFO_CTRL_PANEL_CONFIRMATION_DELETE_SCHEMA_ELEMENTS_MSG.get(
+          Utilities.getStringFromCollection(allNames, ", "));
+    mb.append(confirmationMessage);
+    return mb.toMessage();
+  }
 }
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomAttributePanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomAttributePanel.java
index 75522d5..24de7d0 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomAttributePanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomAttributePanel.java
@@ -29,41 +29,168 @@
 
 import static org.opends.messages.AdminToolMessages.*;
 
+import java.awt.Component;
+import java.awt.Container;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 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.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.File;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+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.DefaultListModel;
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JTextField;
 import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
 
 import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
 import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
+import org.opends.guitools.controlpanel.event.
+ ConfigurationElementCreatedListener;
 import org.opends.guitools.controlpanel.event.ScrollPaneBorderListener;
 import org.opends.guitools.controlpanel.task.DeleteSchemaElementsTask;
+import org.opends.guitools.controlpanel.task.ModifyAttributeTask;
 import org.opends.guitools.controlpanel.task.Task;
+import org.opends.guitools.controlpanel.ui.components.BasicExpander;
+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;
+import org.opends.server.api.ApproximateMatchingRule;
+import org.opends.server.api.AttributeSyntax;
+import org.opends.server.api.EqualityMatchingRule;
+import org.opends.server.api.MatchingRule;
+import org.opends.server.api.OrderingMatchingRule;
+import org.opends.server.api.SubstringMatchingRule;
 import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeUsage;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.types.Schema;
+import org.opends.server.util.ServerConstants;
+import org.opends.server.util.StaticUtils;
 
 /**
  * The panel that displays a custom attribute definition.
  *
  */
-public class CustomAttributePanel extends StandardAttributePanel
+public class CustomAttributePanel extends SchemaElementPanel
 {
   private static final long serialVersionUID = 2850763193735843746L;
   private JButton delete;
+  private JButton saveChanges;
   private AttributeType attribute;
   private String attrName;
   private ScrollPaneBorderListener scrollListener;
 
+  private TitlePanel titlePanel = new TitlePanel(Message.EMPTY,
+      Message.EMPTY);
+  private JLabel lName = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_NAME_LABEL.get());
+  private JLabel lSuperior = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_PARENT_LABEL.get());
+  private JLabel lOID = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_OID_LABEL.get());
+  private JLabel lAliases = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_ALIASES_LABEL.get());
+  private JLabel lOrigin = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_ORIGIN_LABEL.get());
+  private JLabel lFile = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_FILE_LABEL.get());
+  private JLabel lDescription = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_DESCRIPTION_LABEL.get());
+  private JLabel lUsage = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_USAGE_LABEL.get());
+  private JLabel lSyntax = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_SYNTAX_LABEL.get());
+  private JLabel lApproximate = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_APPROXIMATE_MATCHING_RULE_LABEL.get());
+  private JLabel lEquality = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_EQUALITY_MATCHING_RULE_LABEL.get());
+  private JLabel lOrdering = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_ORDERING_MATCHING_RULE_LABEL.get());
+  private JLabel lSubstring = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_ATTRIBUTE_SUBSTRING_MATCHING_RULE_LABEL.get());
+  private JLabel lType = Utilities.createPrimaryLabel();
+
+  private JLabel[] labels = {lName, lSuperior, lOID, lAliases, lOrigin, lFile,
+      lDescription, lUsage, lSyntax, lApproximate,
+      lEquality, lOrdering, lSubstring, lType
+  };
+
+  private JTextField name = Utilities.createMediumTextField();
+  private JComboBox parent = Utilities.createComboBox();
+  private JTextField oid = Utilities.createMediumTextField();
+  private JTextField aliases = Utilities.createLongTextField();
+  private JTextField description = Utilities.createLongTextField();
+  private JTextField origin = Utilities.createLongTextField();
+  private JTextField file = Utilities.createLongTextField();
+  private JComboBox usage = Utilities.createComboBox();
+  private JComboBox syntax = Utilities.createComboBox();
+  private JComboBox approximate = Utilities.createComboBox();
+  private JComboBox equality = Utilities.createComboBox();
+  private JComboBox ordering = Utilities.createComboBox();
+  private JComboBox substring = Utilities.createComboBox();
+  private JCheckBox nonModifiable = Utilities.createCheckBox(
+      INFO_CTRL_PANEL_ATTRIBUTE_NON_MODIFIABLE_LABEL.get());
+  private JCheckBox singleValued = Utilities.createCheckBox(
+      INFO_CTRL_PANEL_ATTRIBUTE_SINGLE_VALUED_LABEL.get());
+  private JCheckBox collective = Utilities.createCheckBox(
+      INFO_CTRL_PANEL_ATTRIBUTE_COLLECTIVE_LABEL.get());
+  private JCheckBox obsolete = Utilities.createCheckBox(
+      INFO_CTRL_PANEL_ATTRIBUTE_OBSOLETE_LABEL.get());
+  private JList requiredBy = new JList(new DefaultListModel());
+  private JList optionalBy = new JList(new DefaultListModel());
+
+  private Set<String> lastAliases = new LinkedHashSet<String>();
+
+  private Message NO_PARENT = INFO_CTRL_PANEL_NO_PARENT_FOR_ATTRIBUTE.get();
+  private Message NO_MATCHING_RULE =
+    INFO_CTRL_PANEL_NO_MATCHING_RULE_FOR_ATTRIBUTE.get();
+
+  private Schema schema;
+
+  private boolean ignoreChangeEvents;
+
+  /**
+   * Default constructor of the panel.
+   *
+   */
+  public CustomAttributePanel()
+  {
+    super();
+    createLayout();
+  }
+
   /**
    * {@inheritDoc}
    */
@@ -81,10 +208,11 @@
     JPanel p = new JPanel(new GridBagLayout());
     p.setOpaque(false);
     p.setBorder(PANEL_BORDER);
-    super.createBasicLayout(p, gbc);
+    createBasicLayout(p, gbc);
     gbc = new GridBagConstraints();
     gbc.weightx = 1.0;
     gbc.weighty = 1.0;
+    gbc.gridwidth = 2;
     gbc.fill = GridBagConstraints.BOTH;
     gbc.gridx = 0;
     gbc.gridy = 0;
@@ -98,6 +226,7 @@
     gbc.anchor = GridBagConstraints.WEST;
     gbc.fill = GridBagConstraints.NONE;
     gbc.insets = new Insets(10, 10, 10, 10);
+    gbc.gridwidth = 1;
     delete = Utilities.createButton(
         INFO_CTRL_PANEL_DELETE_ATTRIBUTE_BUTTON.get());
     delete.setOpaque(false);
@@ -112,6 +241,325 @@
         deleteAttribute();
       }
     });
+
+    gbc.anchor = GridBagConstraints.EAST;
+    gbc.gridx ++;
+    saveChanges =
+      Utilities.createButton(INFO_CTRL_PANEL_SAVE_CHANGES_LABEL.get());
+    saveChanges.setOpaque(false);
+    add(saveChanges, gbc);
+    saveChanges.addActionListener(new ActionListener()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void actionPerformed(ActionEvent ev)
+      {
+        ArrayList<Message> errors = new ArrayList<Message>();
+        saveChanges(false, errors);
+      }
+    });
+  }
+
+  /**
+   * Creates the basic layout of the panel.
+   * @param c the container where all the components will be layed out.
+   * @param gbc the grid bag constraints.
+   */
+  protected void createBasicLayout(Container c, GridBagConstraints gbc)
+  {
+    requiredBy.setVisibleRowCount(5);
+    optionalBy.setVisibleRowCount(9);
+
+    gbc.gridy = 0;
+    gbc.gridwidth = 2;
+    addErrorPane(c, gbc);
+    gbc.gridy ++;
+
+    gbc.anchor = GridBagConstraints.WEST;
+    titlePanel.setTitle(INFO_CTRL_PANEL_ATTRIBUTE_DETAILS.get());
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.insets.top = 5;
+    gbc.insets.bottom = 7;
+    c.add(titlePanel, gbc);
+
+    gbc.insets.bottom = 0;
+    gbc.insets.top = 8;
+    gbc.gridy ++;
+    gbc.gridwidth = 1;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+
+    JComboBox[] comboBoxes = {parent, syntax, approximate,
+        equality, ordering, substring};
+    Message[] defaultValues = {NO_PARENT, Message.EMPTY, NO_MATCHING_RULE,
+        NO_MATCHING_RULE, NO_MATCHING_RULE, NO_MATCHING_RULE
+    };
+    SchemaElementComboBoxCellRenderer renderer = new
+    SchemaElementComboBoxCellRenderer(syntax);
+    for (int i=0; i<comboBoxes.length; i++)
+    {
+      DefaultComboBoxModel model = new DefaultComboBoxModel(
+          new Object[]{defaultValues[i]});
+      comboBoxes[i].setModel(model);
+      comboBoxes[i].setRenderer(renderer);
+    }
+
+    DefaultComboBoxModel model = new DefaultComboBoxModel();
+    for (AttributeUsage us : AttributeUsage.values())
+    {
+      model.addElement(us);
+    }
+    usage.setModel(model);
+    usage.setSelectedItem(AttributeUsage.USER_APPLICATIONS);
+    usage.setRenderer(renderer);
+
+    Component[] basicComps = {name, oid, description,
+        syntax};
+    JLabel[] basicLabels = {lName, lOID, lDescription, lSyntax};
+    JLabel[] basicInlineHelp = new JLabel[] {null, null, null,
+        Utilities.createInlineHelpLabel(
+            INFO_CTRL_PANEL_SYNTAX_INLINE_HELP.get())};
+    add(basicLabels, basicComps, basicInlineHelp, c, gbc);
+
+    BasicExpander[] expanders = new BasicExpander[] {
+        new BasicExpander(INFO_CTRL_PANEL_EXTRA_OPTIONS_EXPANDER.get()),
+        new BasicExpander(
+            INFO_CTRL_PANEL_ATTRIBUTE_TYPE_OPTIONS_EXPANDER.get()),
+        new BasicExpander(INFO_CTRL_PANEL_MATCHING_RULE_OPTIONS_EXPANDER.get())
+    };
+
+    Component[][] comps = {{parent, aliases, origin, file},
+        {usage, singleValued, nonModifiable, collective, obsolete},
+        {approximate, equality, ordering, substring}};
+    JLabel[][] labels = {{lSuperior, lAliases, lOrigin, lFile},
+        {lUsage, lType, null, null, null},
+        {lApproximate, lEquality, lOrdering, lSubstring}};
+    JLabel[][] inlineHelps = {{null,
+      Utilities.createInlineHelpLabel(
+          INFO_CTRL_PANEL_SEPARATED_WITH_COMMAS_HELP.get()), null,
+      Utilities.createInlineHelpLabel(
+          INFO_CTRL_PANEL_SCHEMA_FILE_ATTRIBUTE_HELP.get(File.separator))},
+      {null, null, null, null, null, null},
+      {Utilities.createInlineHelpLabel(
+          INFO_CTRL_PANEL_MATCHING_RULE_APPROXIMATE_HELP.get()),
+        Utilities.createInlineHelpLabel(
+            INFO_CTRL_PANEL_MATCHING_RULE_EQUALITY_HELP.get()),
+        Utilities.createInlineHelpLabel(
+            INFO_CTRL_PANEL_MATCHING_RULE_ORDERING_HELP.get()),
+        Utilities.createInlineHelpLabel(
+            INFO_CTRL_PANEL_MATCHING_RULE_SUBSTRING_HELP.get())
+      }
+    };
+    for (int i=0; i<expanders.length; i++)
+    {
+      gbc.gridwidth = 2;
+      gbc.gridx = 0;
+      gbc.insets.left = 0;
+      c.add(expanders[i], gbc);
+      final JPanel p = new JPanel(new GridBagLayout());
+      gbc.insets.left = 15;
+      gbc.gridy ++;
+      c.add(p, gbc);
+      gbc.gridy ++;
+      p.setOpaque(false);
+
+      GridBagConstraints gbc1 = new GridBagConstraints();
+      gbc1.fill = GridBagConstraints.HORIZONTAL;
+      gbc1.gridy = 0;
+
+      add(labels[i], comps[i], inlineHelps[i], p, gbc1);
+      final BasicExpander expander = expanders[i];
+      ChangeListener changeListener = new ChangeListener()
+      {
+        /**
+         * {@inheritDoc}
+         */
+        public void stateChanged(ChangeEvent e)
+        {
+          p.setVisible(expander.isSelected());
+        }
+      };
+      expander.addChangeListener(changeListener);
+      expander.setSelected(false);
+      changeListener.stateChanged(null);
+    }
+
+    ItemListener itemListener = new ItemListener()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void itemStateChanged(ItemEvent ev)
+      {
+        if (ev.getStateChange() == ItemEvent.SELECTED)
+        {
+          updateDefaultMatchingRuleNames();
+          approximate.setSelectedIndex(0);
+          substring.setSelectedIndex(0);
+          equality.setSelectedIndex(0);
+          ordering.setSelectedIndex(0);
+        }
+      }
+    };
+    syntax.addItemListener(itemListener);
+
+    Message[] msgs = new Message[] {
+        INFO_CTRL_PANEL_REQUIRED_BY_LABEL.get(),
+        INFO_CTRL_PANEL_ALLOWED_BY_LABEL.get()
+        };
+    JList[] lists = {requiredBy, optionalBy};
+
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    for (int i=0; i<msgs.length; i++)
+    {
+      gbc.insets.left = 0;
+      gbc.weightx = 0.0;
+      gbc.gridx = 0;
+      if (i == 0)
+      {
+        gbc.insets.top = 15;
+      }
+      else
+      {
+        gbc.insets.top = 10;
+      }
+      c.add(Utilities.createPrimaryLabel(msgs[i]), gbc);
+      gbc.insets.left = 10;
+      gbc.gridx = 1;
+      if (i == 0)
+      {
+        gbc.weighty = 0.35;
+      }
+      else
+      {
+        gbc.weighty = 0.65;
+      }
+      gbc.weightx = 1.0;
+      c.add(Utilities.createScrollPane(lists[i]), gbc);
+      gbc.gridy ++;
+
+      final JList list = lists[i];
+      MouseAdapter clickListener = new MouseAdapter()
+      {
+        /**
+         * {@inheritDoc}
+         */
+        public void mouseClicked(MouseEvent ev)
+        {
+          if (ev.getClickCount() == 1)
+          {
+            objectClassSelected(list);
+          }
+        }
+      };
+      list.addMouseListener(clickListener);
+
+      KeyAdapter keyListener = new KeyAdapter()
+      {
+        /**
+         * {@inheritDoc}
+         */
+        public void keyTyped(KeyEvent ev)
+        {
+          if ((ev.getKeyChar() == KeyEvent.VK_SPACE) ||
+              (ev.getKeyChar() == KeyEvent.VK_ENTER))
+          {
+            objectClassSelected(list);
+          }
+        }
+      };
+      list.addKeyListener(keyListener);
+    }
+
+    DocumentListener docListener = new DocumentListener()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void insertUpdate(DocumentEvent ev)
+      {
+        checkEnableSaveChanges();
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public void removeUpdate(DocumentEvent ev)
+      {
+        checkEnableSaveChanges();
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public void changedUpdate(DocumentEvent arg0)
+      {
+        checkEnableSaveChanges();
+      }
+    };
+    JTextField[] tfs = {name, description, oid, aliases, origin, file};
+    for (JTextField tf : tfs)
+    {
+      tf.getDocument().addDocumentListener(docListener);
+    }
+
+    ActionListener actionListener = new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        checkEnableSaveChanges();
+      }
+    };
+
+    JComboBox[] combos = {parent, usage, syntax, approximate, equality,
+        ordering, substring};
+    for (JComboBox combo : combos)
+    {
+      combo.addActionListener(actionListener);
+    }
+
+    JCheckBox[] checkBoxes = {nonModifiable, singleValued, collective,
+        obsolete};
+    for (JCheckBox cb : checkBoxes)
+    {
+      cb.addActionListener(actionListener);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean mustCheckUnsavedChanges()
+  {
+    return saveChanges.isEnabled();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public UnsavedChangesDialog.Result checkUnsavedChanges()
+  {
+    UnsavedChangesDialog.Result result;
+    UnsavedChangesDialog unsavedChangesDlg = new UnsavedChangesDialog(
+          Utilities.getParentDialog(this), getInfo());
+    unsavedChangesDlg.setMessage(INFO_CTRL_PANEL_UNSAVED_CHANGES_SUMMARY.get(),
+        INFO_CTRL_PANEL_UNSAVED_ATTRIBUTE_CHANGES_DETAILS.get(
+           attribute.getNameOrOID()));
+    Utilities.centerGoldenMean(unsavedChangesDlg,
+          Utilities.getParentDialog(this));
+    unsavedChangesDlg.setVisible(true);
+    result = unsavedChangesDlg.getResult();
+    if (result == UnsavedChangesDialog.Result.SAVE)
+    {
+      ArrayList<Message> errors = new ArrayList<Message>();
+      saveChanges(true, errors);
+      if (!errors.isEmpty())
+      {
+        result = UnsavedChangesDialog.Result.CANCEL;
+      }
+    }
+
+    return result;
   }
 
   /**
@@ -127,11 +575,119 @@
    */
   public void update(AttributeType attr, Schema schema)
   {
-    super.update(attr, schema);
+    ignoreChangeEvents = true;
+    String n = attr.getPrimaryName();
+    if (n == null)
+    {
+      n = "";
+    }
+    titlePanel.setDetails(Message.raw(n));
+    name.setText(n);
+
+    oid.setText(attr.getOID());
+    n = attr.getDescription();
+    if (n == null)
+    {
+      n = "";
+    }
+    description.setText(n);
+
+    syntax.setSelectedItem(attr.getSyntax());
+
+    AttributeType superior = attr.getSuperiorType();
+    if (superior == null)
+    {
+      parent.setSelectedItem(NO_PARENT);
+    }
+    else
+    {
+      parent.setSelectedItem(superior);
+    }
+    Set<String> aliases = getAliases(attr);
+    lastAliases.clear();
+    lastAliases.addAll(aliases);
+    this.aliases.setText(Utilities.getStringFromCollection(aliases, ", "));
+
+    String sOrigin = Utilities.getOrigin(attr);
+    if (sOrigin == null)
+    {
+      sOrigin = "";
+    }
+    origin.setText(sOrigin);
+
+    String sFile = attr.getSchemaFile();
+    if (sFile == null)
+    {
+      sFile = "";
+    }
+    file.setText(sFile);
+
+    usage.setSelectedItem(attr.getUsage());
+    singleValued.setSelected(attr.isSingleValue());
+    nonModifiable.setSelected(attr.isNoUserModification());
+    collective.setSelected(attr.isCollective());
+    obsolete.setSelected(attr.isObsolete());
+
+    JComboBox[] matchingRules = {approximate, equality, ordering, substring};
+    MatchingRule[] rules = {attr.getApproximateMatchingRule(),
+        attr.getEqualityMatchingRule(), attr.getOrderingMatchingRule(),
+        attr.getSubstringMatchingRule()
+    };
+    for (int i=0; i<matchingRules.length; i++)
+    {
+      if (rules[i] != null)
+      {
+        matchingRules[i].setSelectedItem(rules[i]);
+      }
+      else
+      {
+        matchingRules[i].setSelectedItem(NO_MATCHING_RULE);
+      }
+    }
+
+    Comparator<String> lowerCaseComparator = new LowerCaseComparator();
+    SortedSet<String> requiredByOcs = new TreeSet<String>(lowerCaseComparator);
+    for (ObjectClass oc : schema.getObjectClasses().values())
+    {
+      if (oc.getRequiredAttributeChain().contains(attr))
+      {
+        requiredByOcs.add(oc.getNameOrOID());
+      }
+    }
+
+    DefaultListModel model = (DefaultListModel)requiredBy.getModel();
+    model.clear();
+    for (String oc : requiredByOcs)
+    {
+      model.addElement(oc);
+    }
+
+    SortedSet<String> optionalByOcs = new TreeSet<String>(lowerCaseComparator);
+    for (ObjectClass oc : schema.getObjectClasses().values())
+    {
+      if (oc.getOptionalAttributeChain().contains(attr))
+      {
+        optionalByOcs.add(oc.getNameOrOID());
+      }
+    }
+
+    model = (DefaultListModel)optionalBy.getModel();
+    model.clear();
+    for (String oc : optionalByOcs)
+    {
+      model.addElement(oc);
+    }
     attribute = attr;
-    attrName = attribute.getNameOrOID();
+    attrName = attr.getNameOrOID();
 
     scrollListener.updateBorder();
+
+    for (JLabel label : labels)
+    {
+      setPrimaryValid(label);
+    }
+    saveChanges.setEnabled(false);
+    ignoreChangeEvents = false;
   }
 
   /**
@@ -139,11 +695,146 @@
    */
   public void configurationChanged(ConfigurationChangeEvent ev)
   {
+    ArrayList<AttributeSyntax<?>> newSyntaxes =
+      new ArrayList<AttributeSyntax<?>>();
+
     final ServerDescriptor desc = ev.getNewDescriptor();
+    Schema s = desc.getSchema();
+
+    boolean schemaChanged;
+    if (schema != null && s != null)
+    {
+      schemaChanged = !ServerDescriptor.areSchemasEqual(s, schema);
+    }
+    else if (schema == null && s != null)
+    {
+      schemaChanged = true;
+    }
+    else if (s == null && schema != null)
+    {
+      schemaChanged = false;
+    }
+    else
+    {
+      schemaChanged = false;
+    }
+    if (schemaChanged)
+    {
+      schema = s;
+      HashMap<String, AttributeSyntax<?>> syntaxNameMap = new HashMap<String,
+      AttributeSyntax<?>>();
+      for (String key : schema.getSyntaxes().keySet())
+      {
+        AttributeSyntax<?> syntax = schema.getSyntax(key);
+        String name = syntax.getSyntaxName();
+        if (name == null)
+        {
+          name = syntax.getOID();
+        }
+        syntaxNameMap.put(name, syntax);
+      }
+
+      SortedSet<String> orderedKeys =
+        new TreeSet<String>(syntaxNameMap.keySet());
+      for (String key : orderedKeys)
+      {
+        newSyntaxes.add(syntaxNameMap.get(key));
+      }
+      updateComboBoxModel(newSyntaxes,
+          ((DefaultComboBoxModel)syntax.getModel()));
+
+      HashMap<String, AttributeType> attributeNameMap = new HashMap<String,
+      AttributeType>();
+      for (String key : schema.getAttributeTypes().keySet())
+      {
+        AttributeType attr = schema.getAttributeType(key);
+        attributeNameMap.put(attr.getNameOrOID(), attr);
+      }
+      orderedKeys.clear();
+      orderedKeys.addAll(attributeNameMap.keySet());
+      ArrayList<Object> newParents = new ArrayList<Object>();
+      for (String key : orderedKeys)
+      {
+        newParents.add(attributeNameMap.get(key));
+      }
+      newParents.add(0, NO_PARENT);
+      updateComboBoxModel(newParents,
+          ((DefaultComboBoxModel)parent.getModel()));
+
+      ArrayList<MatchingRule> approximateElements =
+        new ArrayList<MatchingRule>();
+      ArrayList<MatchingRule> equalityElements = new ArrayList<MatchingRule>();
+      ArrayList<MatchingRule> orderingElements = new ArrayList<MatchingRule>();
+      ArrayList<MatchingRule> substringElements = new ArrayList<MatchingRule>();
+
+      HashMap<String, MatchingRule> matchingRuleNameMap = new HashMap<String,
+      MatchingRule>();
+      for (String key : schema.getMatchingRules().keySet())
+      {
+        MatchingRule rule = schema.getMatchingRule(key);
+        matchingRuleNameMap.put(rule.getNameOrOID(), rule);
+      }
+
+      orderedKeys.clear();
+      orderedKeys.addAll(matchingRuleNameMap.keySet());
+      for (String key : orderedKeys)
+      {
+        MatchingRule matchingRule = matchingRuleNameMap.get(key);
+        if (matchingRule instanceof ApproximateMatchingRule)
+        {
+          approximateElements.add(matchingRule);
+        }
+        else if (matchingRule instanceof EqualityMatchingRule)
+        {
+          equalityElements.add(matchingRule);
+        }
+        else if (matchingRule instanceof OrderingMatchingRule)
+        {
+          orderingElements.add(matchingRule);
+        }
+        else if (matchingRule instanceof SubstringMatchingRule)
+        {
+          substringElements.add(matchingRule);
+        }
+      }
+      JComboBox[] combos = {approximate, equality, ordering, substring};
+      ArrayList<ArrayList<MatchingRule>> ruleNames =
+        new ArrayList<ArrayList<MatchingRule>>();
+      ruleNames.add(approximateElements);
+      ruleNames.add(equalityElements);
+      ruleNames.add(orderingElements);
+      ruleNames.add(substringElements);
+      for (int i=0; i<combos.length; i++)
+      {
+        DefaultComboBoxModel model = (DefaultComboBoxModel)combos[i].getModel();
+        ArrayList<Object> el = new ArrayList<Object>();
+        el.addAll(ruleNames.get(i));
+        if (model.getSize() == 0)
+        {
+          el.add(0, NO_MATCHING_RULE);
+        }
+        else
+        {
+          el.add(0, model.getElementAt(0));
+        }
+        updateComboBoxModel(el, model);
+      }
+    }
+    else if (schema == null)
+    {
+      updateErrorPane(errorPane,
+          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
+          ColorAndFontConstants.errorTitleFont,
+          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get(),
+          ColorAndFontConstants.defaultFont);
+    }
+    if (schema != null)
+    {
     updateErrorPaneIfAuthRequired(desc,
         isLocal() ?
-        INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_ATTRIBUTE_DELETE.get() :
+      INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_ATTRIBUTE_DELETE.get() :
       INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname()));
+    }
     SwingUtilities.invokeLater(new Runnable()
     {
       /**
@@ -151,32 +842,55 @@
        */
       public void run()
       {
-        delete.setEnabled(!authenticationRequired(desc));
+        delete.setEnabled(!authenticationRequired(desc) &&
+            delete.isEnabled() &&
+            schema != null);
+        checkEnableSaveChanges();
+        saveChanges.setEnabled(saveChanges.isEnabled() &&
+            !authenticationRequired(desc) &&
+            schema != null);
       }
     });
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  public Component getPreferredFocusComponent()
+  {
+    return name;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void okClicked()
+  {
+  }
+
   private void deleteAttribute()
   {
     ArrayList<Message> errors = new ArrayList<Message>();
+    Schema schema = getInfo().getServerDescriptor().getSchema();
     ProgressDialog dlg = new ProgressDialog(
         Utilities.createFrame(),
         Utilities.getParentDialog(this),
         INFO_CTRL_PANEL_DELETE_ATTRIBUTE_TITLE.get(), getInfo());
-    ArrayList<ObjectClass> ocsToDelete = new ArrayList<ObjectClass>();
-    ArrayList<AttributeType> attrsToDelete = new ArrayList<AttributeType>();
+
+    LinkedHashSet<AttributeType> attrsToDelete =
+      new LinkedHashSet<AttributeType>(1);
     attrsToDelete.add(attribute);
 
-    DeleteSchemaElementsTask newTask = new DeleteSchemaElementsTask(getInfo(),
-        dlg, ocsToDelete, attrsToDelete);
+    Task newTask = new DeleteSchemaElementsTask(getInfo(), dlg,
+        new LinkedHashSet<ObjectClass>(0), attrsToDelete);
     for (Task task : getInfo().getTasks())
     {
       task.canLaunch(newTask, errors);
     }
-    Schema schema = getInfo().getServerDescriptor().getSchema();
+    TreeSet<String> childAttributes = new TreeSet<String>();
+    TreeSet<String> dependentClasses = new TreeSet<String>();
     if (schema != null)
     {
-      ArrayList<String> childAttributes = new ArrayList<String>();
       for (AttributeType attr : schema.getAttributeTypes().values())
       {
         if (attribute.equals(attr.getSuperiorType()))
@@ -184,37 +898,48 @@
           childAttributes.add(attr.getNameOrOID());
         }
       }
-      if (!childAttributes.isEmpty())
-      {
-        errors.add(ERR_CANNOT_DELETE_PARENT_ATTRIBUTE.get(attrName,
-            Utilities.getStringFromCollection(childAttributes, ", "),
-            attrName));
-      }
 
-      ArrayList<String> dependentClasses = new ArrayList<String>();
       for (ObjectClass o : schema.getObjectClasses().values())
       {
         if (o.getRequiredAttributeChain().contains(attribute))
         {
           dependentClasses.add(o.getNameOrOID());
         }
+        else if (o.getOptionalAttributeChain().contains(attribute))
+        {
+          dependentClasses.add(o.getNameOrOID());
+        }
       }
-      if (!dependentClasses.isEmpty())
-      {
-        errors.add(ERR_CANNOT_DELETE_ATTRIBUTE_WITH_DEPENDENCIES.get(
-            attrName,
-            Utilities.getStringFromCollection(dependentClasses, ", "),
-            attrName));
-      }
+    }
+    else
+    {
+      errors.add(ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get());
     }
     if (errors.size() == 0)
     {
+      MessageBuilder mb = new MessageBuilder();
+
+      if (!childAttributes.isEmpty())
+      {
+        mb.append(INFO_ATTRIBUTE_IS_SUPERIOR.get(attrName,
+            Utilities.getStringFromCollection(childAttributes, ", ")));
+        mb.append("<br>");
+      }
+
+      if (!dependentClasses.isEmpty())
+      {
+        mb.append(INFO_ATTRIBUTE_WITH_DEPENDENCIES.get(
+            attrName,
+            Utilities.getStringFromCollection(dependentClasses, ", ")));
+        mb.append("<br>");
+      }
       Message confirmationMessage =
         INFO_CTRL_PANEL_CONFIRMATION_DELETE_ATTRIBUTE_DETAILS.get(
             attribute.getNameOrOID());
+      mb.append(confirmationMessage);
       if (displayConfirmationDialog(
           INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
-          confirmationMessage))
+          mb.toMessage()))
       {
         launchOperation(newTask,
             INFO_CTRL_PANEL_DELETING_ATTRIBUTE_SUMMARY.get(attrName),
@@ -232,4 +957,376 @@
       displayErrorDialog(errors);
     }
   }
+
+  private void saveChanges(boolean modal, ArrayList<Message> errors)
+  {
+    // Check if the aliases or the name have changed
+    for (JLabel label : labels)
+    {
+      setPrimaryValid(label);
+    }
+    String n = getAttributeName();
+    MessageBuilder err = new MessageBuilder();
+    if (n.length() == 0)
+    {
+      errors.add(ERR_CTRL_PANEL_ATTRIBUTE_NAME_REQUIRED.get());
+      setPrimaryInvalid(lName);
+    }
+    else if (!n.equalsIgnoreCase(attribute.getNameOrOID()))
+    {
+      if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
+      {
+        errors.add(ERR_CTRL_PANEL_INVALID_ATTRIBUTE_NAME.get(err.toString()));
+        setPrimaryInvalid(lName);
+        err = new MessageBuilder();
+      }
+      else
+      {
+        Message elementType = NewAttributePanel.getSchemaElementType(n, schema);
+        if (elementType != null)
+        {
+          errors.add(ERR_CTRL_PANEL_ATTRIBUTE_NAME_ALREADY_IN_USE.get(n,
+              elementType.toString()));
+          setPrimaryInvalid(lName);
+        }
+      }
+    }
+    n = oid.getText().trim();
+    if (n.length() > 0 && !n.equalsIgnoreCase(attribute.getOID()))
+    {
+      if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
+      {
+        errors.add(ERR_CTRL_PANEL_OID_NOT_VALID.get(err.toString()));
+        setPrimaryInvalid(lOID);
+        err = new MessageBuilder();
+      }
+      else
+      {
+        Message elementType = NewAttributePanel.getSchemaElementType(n, schema);
+        if (elementType != null)
+        {
+          errors.add(ERR_CTRL_PANEL_OID_ALREADY_IN_USE.get(n,
+              elementType.toString()));
+          setPrimaryInvalid(lOID);
+        }
+      }
+    }
+
+    Collection<String> aliases = getAliases();
+    Collection<String> oldAliases = getAliases(attribute);
+
+    if (!aliases.equals(oldAliases))
+    {
+      for (String alias : aliases)
+      {
+        if (alias.trim().length() == 0)
+        {
+          errors.add(ERR_CTRL_PANEL_EMPTY_ALIAS.get());
+          setPrimaryInvalid(lAliases);
+        }
+        else
+        {
+          boolean notPreviouslyDefined = true;
+          for (String oldAlias : oldAliases)
+          {
+            if (oldAlias.equalsIgnoreCase(alias))
+            {
+              notPreviouslyDefined = false;
+              break;
+            }
+          }
+          if (notPreviouslyDefined)
+          {
+            Message elementType =
+              NewAttributePanel.getSchemaElementType(alias, schema);
+            if (elementType != null)
+            {
+              errors.add(ERR_CTRL_PANEL_ALIAS_ALREADY_IN_USE.get(n,
+                  elementType.toString()));
+              setPrimaryInvalid(lAliases);
+            }
+          }
+        }
+      }
+    }
+
+
+    AttributeType superior = getSuperior();
+    if (superior != null)
+    {
+      if (superior.getNameOrOID().equalsIgnoreCase(attribute.getNameOrOID()))
+      {
+        errors.add(ERR_CTRL_PANEL_ATTRIBUTE_CANNOT_BE_ITS_SUPERIOR.get());
+        setPrimaryInvalid(lSuperior);
+      }
+      else
+      {
+        // Check whether this object class is defined as parent as the superior.
+        superior = superior.getSuperiorType();
+        while (superior != null)
+        {
+          if (superior.getNameOrOID().equalsIgnoreCase(
+              attribute.getNameOrOID()))
+          {
+            errors.add(
+                ERR_CTRL_PANEL_ATTRIBUTE_IS_SUPERIOR_OF_SUPERIOR.get(
+                getSuperior().getNameOrOID()));
+            setPrimaryInvalid(lSuperior);
+            break;
+          }
+          superior = superior.getSuperiorType();
+        }
+      }
+    }
+
+    setPrimaryValid(lUsage);
+    if (nonModifiable.isSelected())
+    {
+      if (AttributeUsage.USER_APPLICATIONS.equals(usage.getSelectedItem()))
+      {
+        errors.add(ERR_NON_MODIFIABLE_CANNOT_BE_USER_APPLICATIONS.get());
+        setPrimaryInvalid(lUsage);
+      }
+    }
+
+    if (errors.size() == 0)
+    {
+      ProgressDialog dlg = new ProgressDialog(
+          Utilities.createFrame(),
+          Utilities.getParentDialog(this),
+          INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TITLE.get(), getInfo());
+
+      ModifyAttributeTask newTask = new ModifyAttributeTask(getInfo(),
+          dlg, attribute, getNewAttribute());
+      for (ConfigurationElementCreatedListener listener :
+        getConfigurationElementCreatedListeners())
+      {
+        newTask.addConfigurationElementCreatedListener(listener);
+      }
+      for (Task task : getInfo().getTasks())
+      {
+        task.canLaunch(newTask, errors);
+      }
+      if (errors.size() == 0)
+      {
+        launchOperation(newTask,
+            INFO_CTRL_PANEL_MODIFYING_ATTRIBUTE_SUMMARY.get(attrName),
+            INFO_CTRL_PANEL_MODIFYING_ATTRIBUTE_COMPLETE.get(),
+            INFO_CTRL_PANEL_MODIFYING_ATTRIBUTE_SUCCESSFUL.get(attrName),
+            ERR_CTRL_PANEL_MODIFYING_ATTRIBUTE_ERROR_SUMMARY.get(),
+            ERR_CTRL_PANEL_MODIFYING_ATTRIBUTE_ERROR_DETAILS.get(attrName),
+            null,
+            dlg);
+        dlg.setVisible(true);
+      }
+    }
+
+    if (!errors.isEmpty())
+    {
+      displayErrorDialog(errors);
+    }
+  }
+
+  private void checkEnableSaveChanges()
+  {
+    if (ignoreChangeEvents) return;
+    boolean changed;
+
+    if (attribute != null)
+    {
+      try
+      {
+        changed = !attribute.toString().equals(getNewAttribute().toString());
+      }
+      catch (Throwable t)
+      {
+        changed = true;
+      }
+    }
+    else
+    {
+      changed = false;
+    }
+    saveChanges.setEnabled(changed);
+  }
+
+  private String getAttributeName()
+  {
+    return name.getText().trim();
+  }
+
+  private String getOID()
+  {
+    String o = oid.getText().trim();
+    if (o.length() == 0)
+    {
+      o = getAttributeName()+"-oid";
+    }
+    return o;
+  }
+
+  private ArrayList<String> getAliases()
+  {
+    ArrayList<String> al = new ArrayList<String>();
+    String s = aliases.getText().trim();
+    if (s.length() > 0)
+    {
+      String[] a = s.split(",");
+      for (String alias : a)
+      {
+        al.add(alias.trim());
+      }
+    }
+    return al;
+  }
+
+  private ArrayList<String> getAllNames()
+  {
+    ArrayList<String> al = new ArrayList<String>();
+    al.add(getAttributeName());
+    al.addAll(getAliases());
+    return al;
+  }
+
+  private AttributeType getSuperior()
+  {
+    Object o = parent.getSelectedItem();
+    if (NO_PARENT.equals(o))
+    {
+      return null;
+    }
+    else
+    {
+      return (AttributeType)o;
+    }
+  }
+
+  private ApproximateMatchingRule getApproximateMatchingRule()
+  {
+    if (approximate.getSelectedIndex() == 0)
+    {
+      return null;
+    }
+    else
+    {
+      return (ApproximateMatchingRule)approximate.getSelectedItem();
+    }
+  }
+
+  private EqualityMatchingRule getEqualityMatchingRule()
+  {
+    if (equality.getSelectedIndex() == 0)
+    {
+      return null;
+    }
+    else
+    {
+      return (EqualityMatchingRule)equality.getSelectedItem();
+    }
+  }
+
+  private SubstringMatchingRule getSubstringMatchingRule()
+  {
+    if (substring.getSelectedIndex() == 0)
+    {
+      return null;
+    }
+    else
+    {
+      return (SubstringMatchingRule)substring.getSelectedItem();
+    }
+  }
+
+  private OrderingMatchingRule getOrderingMatchingRule()
+  {
+    if (ordering.getSelectedIndex() == 0)
+    {
+      return null;
+    }
+    else
+    {
+      return (OrderingMatchingRule)ordering.getSelectedItem();
+    }
+  }
+
+  private Map<String, List<String>> getExtraProperties()
+  {
+    Map<String, List<String>> map = new HashMap<String, List<String>>();
+    String f = file.getText().trim();
+    if (f.length() > 0)
+    {
+      ArrayList<String> list = new ArrayList<String>();
+      list.add(f);
+      map.put(ServerConstants.SCHEMA_PROPERTY_FILENAME, list);
+    }
+    String or = origin.getText().trim();
+    if (or.length() > 0)
+    {
+      ArrayList<String> list = new ArrayList<String>();
+      list.add(or);
+      map.put(ServerConstants.SCHEMA_PROPERTY_ORIGIN, list);
+    }
+    return map;
+  }
+
+  private String getDescription()
+  {
+    return description.getText().trim();
+  }
+
+  private AttributeType getNewAttribute()
+  {
+    AttributeType attr = new AttributeType("", getAttributeName(),
+        getAllNames(),
+        getOID(),
+        getDescription(),
+        getSuperior(),
+        (AttributeSyntax<?>)syntax.getSelectedItem(),
+        getApproximateMatchingRule(),
+        getEqualityMatchingRule(),
+        getOrderingMatchingRule(),
+        getSubstringMatchingRule(),
+        (AttributeUsage)usage.getSelectedItem(),
+        collective.isSelected(), nonModifiable.isSelected(),
+        obsolete.isSelected(), singleValued.isSelected(),
+        getExtraProperties());
+
+    return attr;
+  }
+
+  private void updateDefaultMatchingRuleNames()
+  {
+    AttributeSyntax<?> syn = (AttributeSyntax<?>)syntax.getSelectedItem();
+    if (syn != null)
+    {
+      MatchingRule[] rules = {syn.getApproximateMatchingRule(),
+          syn.getSubstringMatchingRule(),
+          syn.getEqualityMatchingRule(),
+          syn.getOrderingMatchingRule()};
+      JComboBox[] combos = {approximate, substring, equality, ordering};
+      for (int i=0; i<rules.length; i++)
+      {
+        DefaultComboBoxModel model = (DefaultComboBoxModel)combos[i].getModel();
+        int index = combos[i].getSelectedIndex();
+        if (rules[i] != null)
+        {
+          if (model.getSize() > 0)
+          {
+            model.removeElementAt(0);
+          }
+          model.insertElementAt(INFO_CTRL_PANEL_DEFAULT_DEFINED_IN_SYNTAX.get(
+              rules[i].getNameOrOID()), 0);
+        }
+        else
+        {
+          if (model.getSize() > 0)
+          {
+            model.removeElementAt(0);
+          }
+          model.insertElementAt(NO_MATCHING_RULE, 0);
+        }
+        combos[i].setSelectedIndex(index);
+      }
+    }
+  }
 }
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java
index 611c7ae..e883cf3 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/CustomObjectClassPanel.java
@@ -29,41 +29,140 @@
 
 import static org.opends.messages.AdminToolMessages.*;
 
+import java.awt.Component;
+import java.awt.Container;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 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.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+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;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.ListCellRenderer;
 import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
 
 import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
+import org.opends.guitools.controlpanel.datamodel.SortableListModel;
 import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
+import org.opends.guitools.controlpanel.event.
+ ConfigurationElementCreatedListener;
 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.TitlePanel;
+import org.opends.guitools.controlpanel.ui.renderer.
+ SchemaElementComboBoxCellRenderer;
 import org.opends.guitools.controlpanel.util.Utilities;
 import org.opends.messages.Message;
+import org.opends.messages.MessageBuilder;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.ObjectClass;
+import org.opends.server.types.ObjectClassType;
 import org.opends.server.types.Schema;
+import org.opends.server.util.ServerConstants;
+import org.opends.server.util.StaticUtils;
 
 /**
  * The panel that displays a custom object class definition.
  *
  */
-public class CustomObjectClassPanel extends StandardObjectClassPanel
+public class CustomObjectClassPanel extends SchemaElementPanel
 {
   private static final long serialVersionUID = 2105520588901380L;
   private JButton delete;
+  private JButton saveChanges;
   private ObjectClass objectClass;
   private String ocName;
   private ScrollPaneBorderListener scrollListener;
 
+  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(
+      INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get());
+  private JLabel lOID = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_OBJECTCLASS_OID_LABEL.get());
+  private JLabel lAliases = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_OBJECTCLASS_ALIASES_LABEL.get());
+  private JLabel lOrigin = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_OBJECTCLASS_ORIGIN_LABEL.get());
+  private JLabel lFile = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_OBJECTCLASS_FILE_LABEL.get());
+  private JTextField aliases = Utilities.createLongTextField();
+  private JLabel lDescription = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_OBJECTCLASS_DESCRIPTION_LABEL.get());
+  private JLabel lType = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_OBJECTCLASS_TYPE_LABEL.get());
+  private JLabel lAttributes = Utilities.createPrimaryLabel(
+      INFO_CTRL_PANEL_OBJECTCLASS_ATTRIBUTES_LABEL.get());
+
+  private Set<AttributeType> inheritedOptionalAttributes =
+    new HashSet<AttributeType>();
+  private Set<AttributeType> inheritedRequiredAttributes =
+    new HashSet<AttributeType>();
+
+  private JLabel[] labels = {lName, lParent, lOID, lAliases, lOrigin, lFile,
+      lDescription, lType, lAttributes
+  };
+
+  private JTextField name = Utilities.createMediumTextField();
+  private JComboBox parent = Utilities.createComboBox();
+  private JComboBox type = Utilities.createComboBox();
+  private JTextField oid = Utilities.createMediumTextField();
+  private JTextField description = Utilities.createLongTextField();
+  private JTextField origin = Utilities.createLongTextField();
+  private JTextField file = Utilities.createLongTextField();
+  private JCheckBox obsolete = Utilities.createCheckBox(
+      INFO_CTRL_PANEL_OBJECTCLASS_OBSOLETE_LABEL.get());
+  private DoubleAddRemovePanel<AttributeType> attributes;
+
+  private Schema schema;
+  private Set<String> lastAliases = new LinkedHashSet<String>();
+
+  private boolean ignoreChangeEvents;
+
+
+  /**
+   * Default constructor of the panel.
+   *
+   */
+  public CustomObjectClassPanel()
+  {
+    super();
+    createLayout();
+  }
+
   /**
    * {@inheritDoc}
    */
@@ -81,10 +180,11 @@
     GridBagConstraints gbc = new GridBagConstraints();
     p.setOpaque(false);
     p.setBorder(PANEL_BORDER);
-    super.createBasicLayout(p, gbc);
+    createBasicLayout(p, gbc);
     gbc = new GridBagConstraints();
     gbc.weightx = 1.0;
     gbc.weighty = 1.0;
+    gbc.gridwidth = 2;
     gbc.fill = GridBagConstraints.BOTH;
     gbc.gridx = 0;
     gbc.gridy = 0;
@@ -98,6 +198,7 @@
     gbc.anchor = GridBagConstraints.WEST;
     gbc.fill = GridBagConstraints.NONE;
     gbc.insets = new Insets(10, 10, 10, 10);
+    gbc.gridwidth = 1;
     delete = Utilities.createButton(
         INFO_CTRL_PANEL_DELETE_OBJECTCLASS_BUTTON.get());
     delete.setOpaque(false);
@@ -112,6 +213,343 @@
         deleteObjectclass();
       }
     });
+
+    gbc.anchor = GridBagConstraints.EAST;
+    gbc.gridx ++;
+    saveChanges =
+      Utilities.createButton(INFO_CTRL_PANEL_SAVE_CHANGES_LABEL.get());
+    saveChanges.setOpaque(false);
+    add(saveChanges, gbc);
+    saveChanges.addActionListener(new ActionListener()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void actionPerformed(ActionEvent ev)
+      {
+        ArrayList<Message> errors = new ArrayList<Message>();
+        saveChanges(false, errors);
+      }
+    });
+  }
+
+  /**
+   * Creates the basic layout of the panel.
+   * @param c the container where all the components will be layed out.
+   * @param gbc the grid bag constraints.
+   */
+  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()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void itemStateChanged(ItemEvent ev)
+      {
+        if (ignoreChangeEvents) return;
+        updateAttributesWithParent(true);
+      }
+    };
+    parent.addItemListener(itemListener);
+
+    model = new DefaultComboBoxModel();
+    for (ObjectClassType t : ObjectClassType.values())
+    {
+      model.addElement(t);
+    }
+    type.setModel(model);
+    type.setSelectedItem(ObjectClassType.STRUCTURAL);
+    type.setRenderer(renderer);
+
+    attributes =
+      new DoubleAddRemovePanel<AttributeType>(0, AttributeType.class);
+    Comparator<AttributeType> comparator = new Comparator<AttributeType>()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public int compare(AttributeType attr1, AttributeType attr2)
+      {
+        return attr1.getNameOrOID().compareTo(attr2.getNameOrOID());
+      }
+    };
+    attributes.getAvailableListModel().setComparator(comparator);
+    attributes.getSelectedListModel1().setComparator(comparator);
+    attributes.getSelectedListModel2().setComparator(comparator);
+
+    gbc.gridy = 0;
+    gbc.gridwidth = 2;
+    addErrorPane(c, gbc);
+    gbc.gridy ++;
+
+    gbc.anchor = GridBagConstraints.WEST;
+    titlePanel.setTitle(INFO_CTRL_PANEL_OBJECTCLASS_DETAILS.get());
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.insets.top = 5;
+    gbc.insets.bottom = 7;
+    c.add(titlePanel, gbc);
+
+    gbc.insets.bottom = 0;
+    gbc.insets.top = 8;
+    gbc.gridy ++;
+    gbc.gridwidth = 1;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+
+    Component[] basicComps = {name, oid, description, parent};
+    JLabel[] basicLabels = {lName, lOID, lDescription, lParent};
+    JLabel[] basicInlineHelp = new JLabel[] {null, null, null, null};
+    add(basicLabels, basicComps, basicInlineHelp, c, gbc);
+
+    gbc.gridx = 0;
+    gbc.weightx = 0.0;
+    gbc.insets.left = 0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    c.add(lAttributes, gbc);
+
+    gbc.gridx ++;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.weightx = 1.0;
+    gbc.weighty = 1.0;
+    gbc.insets.left = 10;
+    c.add(attributes, gbc);
+    attributes.getAvailableLabel().setText(
+        INFO_CTRL_PANEL_ADDREMOVE_AVAILABLE_ATTRIBUTES.get().toString());
+    attributes.getSelectedLabel1().setText(
+        INFO_CTRL_PANEL_ADDREMOVE_REQUIRED_ATTRIBUTES.get().toString());
+    attributes.getSelectedLabel2().setText(
+        INFO_CTRL_PANEL_ADDREMOVE_OPTIONAL_ATTRIBUTES.get().toString());
+    AttributeTypeCellRenderer listRenderer = new AttributeTypeCellRenderer();
+    attributes.getAvailableList().setCellRenderer(listRenderer);
+    attributes.getSelectedList1().setCellRenderer(listRenderer);
+    attributes.getSelectedList2().setCellRenderer(listRenderer);
+
+    gbc.gridy ++;
+    gbc.weighty = 0.0;
+    gbc.insets.top = 3;
+    JLabel explanation = Utilities.createInlineHelpLabel(
+        INFO_CTRL_PANEL_INHERITED_ATTRIBUTES_HELP.get());
+    gbc.insets.top = 3;
+    c.add(explanation, gbc);
+
+    final BasicExpander expander = new BasicExpander(
+        INFO_CTRL_PANEL_EXTRA_OPTIONS_EXPANDER.get());
+
+    obsolete.setText("Obsolete");
+
+    Component[] comps = {aliases, origin, file, type, obsolete};
+    JLabel[] labels = {lAliases, lOrigin, lFile, lType, null};
+    JLabel[] inlineHelps = {
+        Utilities.createInlineHelpLabel(
+            INFO_CTRL_PANEL_SEPARATED_WITH_COMMAS_HELP.get()), null,
+        Utilities.createInlineHelpLabel(
+            INFO_CTRL_PANEL_SCHEMA_FILE_OBJECTCLASS_HELP.get(File.separator)),
+            null, null};
+    gbc.gridwidth = 2;
+    gbc.gridx = 0;
+    gbc.weighty = 0.0;
+    gbc.insets.left = 0;
+    gbc.gridy ++;
+    c.add(expander, gbc);
+    final JPanel p = new JPanel(new GridBagLayout());
+    gbc.insets.left = 15;
+    gbc.gridy ++;
+    c.add(p, gbc);
+    gbc.gridy ++;
+    p.setOpaque(false);
+
+    GridBagConstraints gbc1 = new GridBagConstraints();
+    gbc1.fill = GridBagConstraints.HORIZONTAL;
+    gbc1.gridy = 0;
+
+    add(labels, comps, inlineHelps, p, gbc1);
+    ChangeListener changeListener = new ChangeListener()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void stateChanged(ChangeEvent e)
+      {
+        p.setVisible(expander.isSelected());
+      }
+    };
+    expander.addChangeListener(changeListener);
+    expander.setSelected(false);
+    changeListener.stateChanged(null);
+
+    DocumentListener docListener = new DocumentListener()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void insertUpdate(DocumentEvent ev)
+      {
+        checkEnableSaveChanges();
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public void removeUpdate(DocumentEvent ev)
+      {
+        checkEnableSaveChanges();
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public void changedUpdate(DocumentEvent arg0)
+      {
+        checkEnableSaveChanges();
+      }
+    };
+    JTextField[] tfs = {name, description, oid, aliases, origin, file};
+    for (JTextField tf : tfs)
+    {
+      tf.getDocument().addDocumentListener(docListener);
+    }
+
+    ActionListener actionListener = new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        checkEnableSaveChanges();
+      }
+    };
+
+    JComboBox[] combos = {parent, type};
+    for (JComboBox combo : combos)
+    {
+      combo.addActionListener(actionListener);
+    }
+
+    ListDataListener dataListener = new ListDataListener()
+    {
+      /**
+       * {@inheritDoc}
+       */
+      public void contentsChanged(ListDataEvent e)
+      {
+        checkEnableSaveChanges();
+      }
+      /**
+       * {@inheritDoc}
+       */
+      public void intervalAdded(ListDataEvent e)
+      {
+        checkEnableSaveChanges();
+      }
+      /**
+       * {@inheritDoc}
+       */
+      public void intervalRemoved(ListDataEvent e)
+      {
+        checkEnableSaveChanges();
+      }
+    };
+    SortableListModel<AttributeType> list1 = attributes.getSelectedListModel1();
+    SortableListModel<AttributeType> list2 = attributes.getSelectedListModel2();
+    list1.addListDataListener(dataListener);
+    list2.addListDataListener(dataListener);
+
+    obsolete.addActionListener(actionListener);
+  }
+
+  /**
+   * Updates the contents of the panel with the provided object class.
+   * @param oc the object class.
+   * @param schema the schema.
+   */
+  public void update(ObjectClass oc, Schema schema)
+  {
+    ignoreChangeEvents = true;
+
+    objectClass = oc;
+    if ((oc == null) || (schema == null))
+    {
+      // Ignore: this is called to get an initial panel size.
+      return;
+    }
+    String n = oc.getPrimaryName();
+    if (n == null)
+    {
+      n = NOT_APPLICABLE.toString();
+    }
+    titlePanel.setDetails(Message.raw(n));
+    name.setText(n);
+
+    SortableListModel<AttributeType> modelRequired =
+      attributes.getSelectedListModel1();
+    SortableListModel<AttributeType> modelAvailable =
+      attributes.getSelectedListModel2();
+    SortableListModel<AttributeType> availableModel =
+      attributes.getAvailableListModel();
+    availableModel.addAll(modelRequired.getData());
+    availableModel.addAll(modelAvailable.getData());
+    modelRequired.clear();
+    modelAvailable.clear();
+
+    parent.setSelectedItem(oc.getSuperiorClass());
+
+    updateAttributesWithParent(false);
+
+    for (AttributeType attr : oc.getRequiredAttributes())
+    {
+      availableModel.remove(attr);
+      modelRequired.add(attr);
+    }
+    for (AttributeType attr : oc.getOptionalAttributes())
+    {
+      availableModel.remove(attr);
+      modelAvailable.add(attr);
+    }
+    notifyAttributesChanged();
+
+    oid.setText(oc.getOID());
+    n = oc.getDescription();
+    if (n == null)
+    {
+      n = "";
+    }
+    description.setText(n);
+
+    Set<String> aliases = getAliases(oc);
+    lastAliases.clear();
+    lastAliases.addAll(aliases);
+    this.aliases.setText(Utilities.getStringFromCollection(aliases, ", "));
+
+    String sOrigin = Utilities.getOrigin(oc);
+    if (sOrigin == null)
+    {
+      sOrigin = "";
+    }
+    origin.setText(sOrigin);
+
+    String sFile = oc.getSchemaFile();
+    if (sFile == null)
+    {
+      sFile = "";
+    }
+    file.setText(sFile);
+
+    type.setSelectedItem(oc.getObjectClassType());
+
+    obsolete.setSelected(oc.isObsolete());
+
+    ocName = objectClass.getNameOrOID();
+    scrollListener.updateBorder();
+    for (JLabel label : labels)
+    {
+      setPrimaryValid(label);
+    }
+    saveChanges.setEnabled(false);
+    ignoreChangeEvents = false;
   }
 
   /**
@@ -120,10 +558,67 @@
   public void configurationChanged(ConfigurationChangeEvent ev)
   {
     final ServerDescriptor desc = ev.getNewDescriptor();
-    updateErrorPaneIfAuthRequired(desc,
-       isLocal() ?
-          INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_OBJECTCLASS_DELETE.get() :
+    Schema s = desc.getSchema();
+    final boolean schemaChanged;
+    if (schema != null && s != null)
+    {
+      schemaChanged = !ServerDescriptor.areSchemasEqual(s, schema);
+    }
+    else if (schema == null && s != null)
+    {
+      schemaChanged = true;
+    }
+    else if (s == null && schema != null)
+    {
+      schemaChanged = false;
+    }
+    else
+    {
+      schemaChanged = false;
+    }
+    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>();
+      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() :
       INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname()));
+    }
+    else if (schema == null)
+    {
+      updateErrorPane(errorPane,
+          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
+          ColorAndFontConstants.errorTitleFont,
+          ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get(),
+          ColorAndFontConstants.defaultFont);
+    }
     SwingUtilities.invokeLater(new Runnable()
     {
       /**
@@ -131,7 +626,18 @@
        */
       public void run()
       {
-        delete.setEnabled(!authenticationRequired(desc));
+        delete.setEnabled(!authenticationRequired(desc)
+            && !authenticationRequired(desc)
+            && schema != null);
+        checkEnableSaveChanges();
+        saveChanges.setEnabled(saveChanges.isEnabled() &&
+            !authenticationRequired(desc)
+            && !authenticationRequired(desc)
+            && schema != null);
+        if (schemaChanged)
+        {
+          updateAttributes();
+        }
       }
     });
   }
@@ -139,15 +645,52 @@
   /**
    * {@inheritDoc}
    */
-  public void update(ObjectClass oc, Schema schema)
+  public boolean mustCheckUnsavedChanges()
   {
-    super.update(oc, schema);
-    objectClass = oc;
-    if (objectClass != null)
+    return saveChanges.isEnabled();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public UnsavedChangesDialog.Result checkUnsavedChanges()
+  {
+    UnsavedChangesDialog.Result result;
+    UnsavedChangesDialog unsavedChangesDlg = new UnsavedChangesDialog(
+          Utilities.getParentDialog(this), getInfo());
+    unsavedChangesDlg.setMessage(INFO_CTRL_PANEL_UNSAVED_CHANGES_SUMMARY.get(),
+        INFO_CTRL_PANEL_UNSAVED_OBJECTCLASS_CHANGES_DETAILS.get(
+           objectClass.getNameOrOID()));
+    Utilities.centerGoldenMean(unsavedChangesDlg,
+          Utilities.getParentDialog(this));
+    unsavedChangesDlg.setVisible(true);
+    result = unsavedChangesDlg.getResult();
+    if (result == UnsavedChangesDialog.Result.SAVE)
     {
-      ocName = objectClass.getNameOrOID();
+      ArrayList<Message> errors = new ArrayList<Message>();
+      saveChanges(true, errors);
+      if (!errors.isEmpty())
+      {
+        result = UnsavedChangesDialog.Result.CANCEL;
+      }
     }
-    scrollListener.updateBorder();
+
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Component getPreferredFocusComponent()
+  {
+    return name;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void okClicked()
+  {
   }
 
   private void deleteObjectclass()
@@ -157,9 +700,10 @@
         Utilities.createFrame(),
         Utilities.getParentDialog(this),
         INFO_CTRL_PANEL_DELETE_OBJECTCLASS_TITLE.get(), getInfo());
-    ArrayList<ObjectClass> ocsToDelete = new ArrayList<ObjectClass>();
+    LinkedHashSet<ObjectClass> ocsToDelete = new LinkedHashSet<ObjectClass>();
     ocsToDelete.add(objectClass);
-    ArrayList<AttributeType> attrsToDelete = new ArrayList<AttributeType>();
+    LinkedHashSet<AttributeType> attrsToDelete =
+      new LinkedHashSet<AttributeType>(0);
 
     DeleteSchemaElementsTask newTask = new DeleteSchemaElementsTask(getInfo(),
         dlg, ocsToDelete, attrsToDelete);
@@ -168,9 +712,9 @@
       task.canLaunch(newTask, errors);
     }
     Schema schema = getInfo().getServerDescriptor().getSchema();
+    ArrayList<String> childClasses = new ArrayList<String>();
     if (schema != null)
     {
-      ArrayList<String> childClasses = new ArrayList<String>();
       for (ObjectClass o : schema.getObjectClasses().values())
       {
         if (objectClass.equals(o.getSuperiorClass()))
@@ -178,17 +722,26 @@
           childClasses.add(o.getNameOrOID());
         }
       }
-      if (!childClasses.isEmpty())
-      {
-        errors.add(ERR_CANNOT_DELETE_PARENT_OBJECTCLASS.get(ocName,
-            Utilities.getStringFromCollection(childClasses, ", "), ocName));
-      }
+    }
+    else
+    {
+      errors.add(ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_DETAILS.get());
     }
     if (errors.size() == 0)
     {
+      MessageBuilder mb = new MessageBuilder();
+
+      if (!childClasses.isEmpty())
+      {
+        mb.append(INFO_OBJECTCLASS_IS_SUPERIOR.get(
+            ocName,
+            Utilities.getStringFromCollection(childClasses, ", ")));
+        mb.append("<br>");
+      }
       Message confirmationMessage =
         INFO_CTRL_PANEL_CONFIRMATION_DELETE_OBJECTCLASS_DETAILS.get(
             ocName);
+      mb.append(confirmationMessage);
       if (displayConfirmationDialog(
           INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
           confirmationMessage))
@@ -209,4 +762,476 @@
       displayErrorDialog(errors);
     }
   }
+
+  private void saveChanges(boolean modal, ArrayList<Message> errors)
+  {
+    for (JLabel label : labels)
+    {
+      setPrimaryValid(label);
+    }
+    String n = getObjectClassName();
+    MessageBuilder err = new MessageBuilder();
+    if (n.length() == 0)
+    {
+      errors.add(ERR_CTRL_PANEL_OBJECTCLASS_NAME_REQUIRED.get());
+      setPrimaryInvalid(lName);
+    }
+    else if (!n.equalsIgnoreCase(objectClass.getNameOrOID()))
+    {
+      if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
+      {
+        errors.add(ERR_CTRL_PANEL_INVALID_OBJECTCLASS_NAME.get(err.toString()));
+        setPrimaryInvalid(lName);
+        err = new MessageBuilder();
+      }
+      else
+      {
+        Message elementType = NewAttributePanel.getSchemaElementType(n, schema);
+        if (elementType != null)
+        {
+          errors.add(ERR_CTRL_PANEL_OBJECTCLASS_NAME_ALREADY_IN_USE.get(n,
+              elementType.toString()));
+          setPrimaryInvalid(lName);
+        }
+      }
+    }
+    n = oid.getText().trim();
+    if (n.length() > 0 && !n.equalsIgnoreCase(objectClass.getOID()))
+    {
+      if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
+      {
+        errors.add(ERR_CTRL_PANEL_OID_NOT_VALID.get(err.toString()));
+        setPrimaryInvalid(lOID);
+        err = new MessageBuilder();
+      }
+      else
+      {
+        Message elementType = NewAttributePanel.getSchemaElementType(n, schema);
+        if (elementType != null)
+        {
+          errors.add(ERR_CTRL_PANEL_OID_ALREADY_IN_USE.get(n,
+              elementType.toString()));
+          setPrimaryInvalid(lOID);
+        }
+      }
+    }
+
+    Collection<String> aliases = getAliases();
+    Collection<String> oldAliases = getAliases(objectClass);
+
+    if (!aliases.equals(oldAliases))
+    {
+      for (String alias : aliases)
+      {
+        if (alias.trim().length() == 0)
+        {
+          errors.add(ERR_CTRL_PANEL_EMPTY_ALIAS.get());
+          setPrimaryInvalid(lAliases);
+        }
+        else
+        {
+          boolean notPreviouslyDefined = true;
+          for (String oldAlias : oldAliases)
+          {
+            if (oldAlias.equalsIgnoreCase(alias))
+            {
+              notPreviouslyDefined = false;
+              break;
+            }
+          }
+          if (notPreviouslyDefined)
+          {
+            Message elementType =
+              NewAttributePanel.getSchemaElementType(alias, schema);
+            if (elementType != null)
+            {
+              errors.add(ERR_CTRL_PANEL_ALIAS_ALREADY_IN_USE.get(n,
+                  elementType.toString()));
+              setPrimaryInvalid(lAliases);
+            }
+          }
+        }
+      }
+    }
+
+
+    ObjectClass superior = getSuperior();
+    if (superior != null)
+    {
+      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();
+        }
+      }
+    }
+
+    if (errors.size() == 0)
+    {
+      ProgressDialog dlg = new ProgressDialog(
+          Utilities.createFrame(),
+          Utilities.getParentDialog(this),
+          INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TITLE.get(), getInfo());
+
+      ModifyObjectClassTask newTask = new ModifyObjectClassTask(getInfo(),
+          dlg, objectClass, getNewObjectClass());
+      for (ConfigurationElementCreatedListener listener :
+        getConfigurationElementCreatedListeners())
+      {
+        newTask.addConfigurationElementCreatedListener(listener);
+      }
+      for (Task task : getInfo().getTasks())
+      {
+        task.canLaunch(newTask, errors);
+      }
+      if (errors.size() == 0)
+      {
+        launchOperation(newTask,
+            INFO_CTRL_PANEL_MODIFYING_OBJECTCLASS_SUMMARY.get(ocName),
+            INFO_CTRL_PANEL_MODIFYING_OBJECTCLASS_COMPLETE.get(),
+            INFO_CTRL_PANEL_MODIFYING_OBJECTCLASS_SUCCESSFUL.get(ocName),
+            ERR_CTRL_PANEL_MODIFYING_OBJECTCLASS_ERROR_SUMMARY.get(),
+            ERR_CTRL_PANEL_MODIFYING_OBJECTCLASS_ERROR_DETAILS.get(ocName),
+            null,
+            dlg);
+        dlg.setVisible(true);
+      }
+    }
+
+    if (!errors.isEmpty())
+    {
+      displayErrorDialog(errors);
+    }
+  }
+
+  private void checkEnableSaveChanges()
+  {
+    if (ignoreChangeEvents) return;
+    boolean changed;
+
+    if (objectClass != null)
+    {
+      try
+      {
+        changed = !objectClass.toString().equals(
+            getNewObjectClass().toString());
+      }
+      catch (Throwable t)
+      {
+        changed = true;
+      }
+    }
+    else
+    {
+      changed = false;
+    }
+    saveChanges.setEnabled(changed);
+  }
+
+  private Set<String> getAliases()
+  {
+    Set<String> al = new LinkedHashSet<String>();
+    String s = aliases.getText().trim();
+    if (s.length() > 0)
+    {
+      String[] a = s.split(",");
+      for (String alias : a)
+      {
+        al.add(alias.trim());
+      }
+    }
+    return al;
+  }
+
+  private String getObjectClassName()
+  {
+    return name.getText().trim();
+  }
+
+  private String getOID()
+  {
+    String o = oid.getText().trim();
+    if (o.length() == 0)
+    {
+      o = getObjectClassName()+"-oid";
+    }
+    return o;
+  }
+
+  private Map<String, List<String>> getExtraProperties()
+  {
+    Map<String, List<String>> map = new HashMap<String, List<String>>();
+    String f = file.getText().trim();
+    if (f.length() > 0)
+    {
+      ArrayList<String> list = new ArrayList<String>();
+      list.add(f);
+      map.put(ServerConstants.SCHEMA_PROPERTY_FILENAME, list);
+    }
+    String or = origin.getText().trim();
+    if (or.length() > 0)
+    {
+      ArrayList<String> list = new ArrayList<String>();
+      list.add(or);
+      map.put(ServerConstants.SCHEMA_PROPERTY_ORIGIN, list);
+    }
+    return map;
+  }
+
+  private ArrayList<String> getAllNames()
+  {
+    ArrayList<String> al = new ArrayList<String>();
+    al.add(getObjectClassName());
+    al.addAll(getAliases());
+    return al;
+  }
+
+  private String getDescription()
+  {
+    return description.getText().trim();
+  }
+
+  private ObjectClass getSuperior()
+  {
+    return (ObjectClass)parent.getSelectedItem();
+  }
+
+  private ObjectClassType getObjectClassType()
+  {
+    return (ObjectClassType)type.getSelectedItem();
+  }
+
+  private Set<AttributeType> getRequiredAttributes()
+  {
+    HashSet<AttributeType> attrs = new HashSet<AttributeType>();
+    attrs.addAll(attributes.getSelectedListModel1().getData());
+    attrs.removeAll(inheritedRequiredAttributes);
+    return attrs;
+  }
+
+  private Set<AttributeType> getOptionalAttributes()
+  {
+    HashSet<AttributeType> attrs = new HashSet<AttributeType>();
+    attrs.addAll(attributes.getSelectedListModel2().getData());
+    attrs.removeAll(inheritedOptionalAttributes);
+    return attrs;
+  }
+
+  private ObjectClass getNewObjectClass()
+  {
+    ObjectClass newObjectClass = new ObjectClass("",
+        getObjectClassName(),
+        getAllNames(),
+        getOID(),
+        getDescription(),
+        getSuperior(),
+        getRequiredAttributes(),
+        getOptionalAttributes(),
+        getObjectClassType(),
+        obsolete.isSelected(),
+        getExtraProperties());
+
+    return newObjectClass;
+  }
+
+  private void updateAttributes()
+  {
+    int[][] selected =
+    {
+      attributes.getAvailableList().getSelectedIndices(),
+      attributes.getSelectedList1().getSelectedIndices(),
+      attributes.getSelectedList2().getSelectedIndices()
+    };
+    JList[] lists =
+    {
+        attributes.getAvailableList(),
+        attributes.getSelectedList1(),
+        attributes.getSelectedList2()
+    };
+    attributes.getAvailableListModel().clear();
+    Collection<AttributeType> allAttrs =
+      schema.getAttributeTypes().values();
+    attributes.getAvailableListModel().addAll(allAttrs);
+
+
+    HashSet<AttributeType> toDelete = new HashSet<AttributeType>();
+    for (AttributeType attr : attributes.getSelectedListModel1().getData())
+    {
+      if (!allAttrs.contains(attr))
+      {
+        toDelete.add(attr);
+      }
+      else
+      {
+        attributes.getAvailableListModel().remove(attr);
+      }
+    }
+    for (AttributeType attr : toDelete)
+    {
+      attributes.getSelectedListModel1().remove(attr);
+    }
+
+    toDelete = new HashSet<AttributeType>();
+    for (AttributeType attr : attributes.getSelectedListModel2().getData())
+    {
+      if (!allAttrs.contains(attr))
+      {
+        toDelete.add(attr);
+      }
+      else
+      {
+        attributes.getAvailableListModel().remove(attr);
+      }
+    }
+    for (AttributeType attr : toDelete)
+    {
+      attributes.getSelectedListModel1().remove(attr);
+    }
+
+    int i = 0;
+    for (int[] sel : selected)
+    {
+      if (sel != null)
+      {
+        ArrayList<Integer> indexes = new ArrayList<Integer>();
+        for (int j=0; j<sel.length; j++)
+        {
+          if (sel[j] < lists[i].getModel().getSize())
+          {
+            indexes.add(sel[j]);
+          }
+        }
+        int[] newSelection = new int[indexes.size()];
+        for (int j=0; j<newSelection.length; j++)
+        {
+          newSelection[j] = indexes.get(j);
+        }
+        lists[i].setSelectedIndices(newSelection);
+      }
+      i++;
+    }
+  }
+
+  private void updateAttributesWithParent(boolean notify)
+  {
+ // Remove the previous inherited attributes.
+    for (AttributeType attr : inheritedRequiredAttributes)
+    {
+      attributes.getAvailableListModel().add(attr);
+      attributes.getSelectedListModel1().remove(attr);
+    }
+    for (AttributeType attr : inheritedOptionalAttributes)
+    {
+      attributes.getAvailableListModel().add(attr);
+      attributes.getSelectedListModel2().remove(attr);
+    }
+
+    inheritedOptionalAttributes.clear();
+    inheritedRequiredAttributes.clear();
+    ObjectClass p = (ObjectClass)parent.getSelectedItem();
+    if (p != null)
+    {
+      for (AttributeType attr : p.getRequiredAttributeChain())
+      {
+        inheritedRequiredAttributes.add(attr);
+      }
+      for (AttributeType attr : p.getOptionalAttributeChain())
+      {
+        inheritedOptionalAttributes.add(attr);
+      }
+    }
+    for (AttributeType attr : inheritedRequiredAttributes)
+    {
+      attributes.getAvailableListModel().remove(attr);
+      attributes.getSelectedListModel1().add(attr);
+    }
+    for (AttributeType attr : inheritedOptionalAttributes)
+    {
+      attributes.getAvailableListModel().remove(attr);
+      attributes.getSelectedListModel2().add(attr);
+    }
+
+    Collection<AttributeType> unmovableItems =
+      new ArrayList<AttributeType>(inheritedRequiredAttributes);
+    unmovableItems.addAll(inheritedOptionalAttributes);
+    attributes.setUnmovableItems(unmovableItems);
+
+    if (notify)
+    {
+      notifyAttributesChanged();
+    }
+  }
+
+  private void notifyAttributesChanged()
+  {
+    attributes.getAvailableListModel().fireContentsChanged(
+        attributes.getAvailableList(), 0,
+        attributes.getAvailableListModel().getSize() - 1);
+    attributes.getSelectedListModel1().fireContentsChanged(
+        attributes.getSelectedList1(), 0,
+        attributes.getSelectedListModel1().getSize() - 1);
+    attributes.getSelectedListModel2().fireContentsChanged(
+        attributes.getSelectedList2(), 0,
+        attributes.getSelectedListModel2().getSize() - 1);
+  }
+
+
+  /**
+   * A renderer for the attribute lists.  The renderer basically marks the
+   * inherited attributes with an asterisk.
+   *
+   */
+  private class AttributeTypeCellRenderer implements ListCellRenderer
+  {
+    private ListCellRenderer defaultRenderer;
+
+    /**
+     * Renderer constructor.
+     *
+     */
+    public AttributeTypeCellRenderer()
+    {
+      defaultRenderer = attributes.getAvailableList().getCellRenderer();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Component getListCellRendererComponent(JList list, Object value,
+        int index, boolean isSelected, boolean cellHasFocus)
+    {
+      if (value instanceof AttributeType)
+      {
+        AttributeType attr = (AttributeType)value;
+        if (inheritedOptionalAttributes.contains(value) ||
+            inheritedRequiredAttributes.contains(value))
+        {
+          value = attr.getNameOrOID()+ " (*)";
+        }
+        else
+        {
+          value = attr.getNameOrOID();
+        }
+      }
+      return defaultRenderer.getListCellRendererComponent(list, value, index,
+          isSelected, cellHasFocus);
+    }
+  }
 }
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewAttributePanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewAttributePanel.java
index 331cfbd..0510440 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewAttributePanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewAttributePanel.java
@@ -37,15 +37,12 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import javax.naming.NamingException;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.ModificationItem;
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
@@ -56,12 +53,11 @@
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
-import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
 import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
 import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
-import org.opends.guitools.controlpanel.task.OfflineUpdateException;
-import org.opends.guitools.controlpanel.task.OnlineUpdateException;
-import org.opends.guitools.controlpanel.task.SchemaTask;
+import org.opends.guitools.controlpanel.event.
+ ConfigurationElementCreatedListener;
+import org.opends.guitools.controlpanel.task.NewSchemaElementsTask;
 import org.opends.guitools.controlpanel.task.Task;
 import org.opends.guitools.controlpanel.ui.components.BasicExpander;
 import
@@ -78,18 +74,8 @@
 import org.opends.server.config.ConfigConstants;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.AttributeUsage;
-import org.opends.server.types.Attributes;
-import org.opends.server.types.CommonSchemaElements;
-import org.opends.server.types.Entry;
-import org.opends.server.types.ExistingFileBehavior;
-import org.opends.server.types.LDIFExportConfig;
-import org.opends.server.types.LDIFImportConfig;
-import org.opends.server.types.Modification;
-import org.opends.server.types.ModificationType;
-import org.opends.server.types.OpenDsException;
+import org.opends.server.types.ObjectClass;
 import org.opends.server.types.Schema;
-import org.opends.server.util.LDIFReader;
-import org.opends.server.util.LDIFWriter;
 import org.opends.server.util.ServerConstants;
 import org.opends.server.util.StaticUtils;
 
@@ -207,22 +193,39 @@
     final boolean[] repack = {firstSchema};
     final boolean[] error = {false};
 
-    if (s != null)
+    boolean schemaChanged;
+    if (schema != null && s != null)
+    {
+      schemaChanged = !ServerDescriptor.areSchemasEqual(s, schema);
+    }
+    else if (schema == null && s != null)
+    {
+      schemaChanged = true;
+    }
+    else if (s == null && schema != null)
+    {
+      schemaChanged = false;
+    }
+    else
+    {
+      schemaChanged = false;
+    }
+    if (schemaChanged)
     {
       schema = s;
 
-     HashMap<String, AttributeSyntax<?>> syntaxNameMap = new HashMap<String,
-     AttributeSyntax<?>>();
-     for (String key : schema.getSyntaxes().keySet())
-     {
-       AttributeSyntax<?> syntax = schema.getSyntax(key);
-       String name = syntax.getSyntaxName();
-       if (name == null)
-       {
-         name = syntax.getOID();
-       }
-       syntaxNameMap.put(name, syntax);
-     }
+      HashMap<String, AttributeSyntax<?>> syntaxNameMap = new HashMap<String,
+      AttributeSyntax<?>>();
+      for (String key : schema.getSyntaxes().keySet())
+      {
+        AttributeSyntax<?> syntax = schema.getSyntax(key);
+        String name = syntax.getSyntaxName();
+        if (name == null)
+        {
+          name = syntax.getOID();
+        }
+        syntaxNameMap.put(name, syntax);
+      }
 
       SortedSet<String> orderedKeys =
         new TreeSet<String>(syntaxNameMap.keySet());
@@ -310,7 +313,7 @@
         updateComboBoxModel(el, model);
       }
     }
-    else
+    else if (schema == null)
     {
       updateErrorPane(errorPane,
           ERR_CTRL_PANEL_SCHEMA_NOT_FOUND_SUMMARY.get(),
@@ -383,10 +386,12 @@
     if (n.length() == 0)
     {
       errors.add(ERR_CTRL_PANEL_ATTRIBUTE_NAME_REQUIRED.get());
+      setPrimaryInvalid(lName);
     }
     else if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
     {
       errors.add(ERR_CTRL_PANEL_INVALID_ATTRIBUTE_NAME.get(err.toString()));
+      setPrimaryInvalid(lName);
       err = new MessageBuilder();
     }
     else
@@ -396,6 +401,7 @@
       {
         errors.add(ERR_CTRL_PANEL_ATTRIBUTE_NAME_ALREADY_IN_USE.get(n,
             elementType.toString()));
+        setPrimaryInvalid(lName);
       }
     }
 
@@ -405,6 +411,7 @@
       if (!StaticUtils.isValidSchemaElement(n, 0, n.length(), err))
       {
         errors.add(ERR_CTRL_PANEL_OID_NOT_VALID.get(err.toString()));
+        setPrimaryInvalid(lOID);
         err = new MessageBuilder();
       }
       else
@@ -414,6 +421,7 @@
         {
           errors.add(ERR_CTRL_PANEL_OID_ALREADY_IN_USE.get(n,
               elementType.toString()));
+          setPrimaryInvalid(lOID);
         }
       }
     }
@@ -428,6 +436,7 @@
           if (alias.trim().length() == 0)
           {
             errors.add(ERR_CTRL_PANEL_EMPTY_ALIAS.get());
+            setPrimaryInvalid(lAliases);
           }
           else
           {
@@ -436,24 +445,44 @@
             {
               errors.add(ERR_CTRL_PANEL_ALIAS_ALREADY_IN_USE.get(n,
                   elementType.toString()));
+              setPrimaryInvalid(lAliases);
             }
           }
         }
       }
     }
 
+    setPrimaryValid(lUsage);
+    if (nonModifiable.isSelected())
+    {
+      if (AttributeUsage.USER_APPLICATIONS.equals(usage.getSelectedItem()))
+      {
+        errors.add(ERR_NON_MODIFIABLE_CANNOT_BE_USER_APPLICATIONS.get());
+        setPrimaryInvalid(lUsage);
+      }
+    }
+
     ProgressDialog dlg = new ProgressDialog(
         Utilities.createFrame(),
         Utilities.getParentDialog(this),
         INFO_CTRL_PANEL_NEW_ATTRIBUTE_PANEL_TITLE.get(), getInfo());
-    NewAttributeTask newTask = null;
+    NewSchemaElementsTask newTask = null;
     if (errors.size() == 0)
     {
-      newTask = new NewAttributeTask(getInfo(), dlg);
+      LinkedHashSet<AttributeType> attributes =
+        new LinkedHashSet<AttributeType>();
+      attributes.add(getAttribute());
+      LinkedHashSet<ObjectClass> ocs = new LinkedHashSet<ObjectClass>(0);
+      newTask = new NewSchemaElementsTask(getInfo(), dlg, ocs, attributes);
       for (Task task : getInfo().getTasks())
       {
         task.canLaunch(newTask, errors);
       }
+      for (ConfigurationElementCreatedListener listener :
+        getConfigurationElementCreatedListeners())
+      {
+        newTask.addConfigurationElementCreatedListener(listener);
+      }
     }
     if (errors.size() == 0)
     {
@@ -834,11 +863,17 @@
     return map;
   }
 
+  private String getDescription()
+  {
+    return description.getText().trim();
+  }
+
   private AttributeType getAttribute()
   {
     AttributeType attr = new AttributeType("", getAttributeName(),
         getAllNames(),
-        getOID(), description.getText().trim(),
+        getOID(),
+        getDescription(),
         getSuperior(),
         (AttributeSyntax<?>)syntax.getSelectedItem(),
         getApproximateMatchingRule(),
@@ -852,228 +887,4 @@
 
     return attr;
   }
-
-  /**
-   * The task in charge of creating the attribute.
-   *
-   */
-  protected class NewAttributeTask extends SchemaTask
-  {
-    private AttributeType attribute;
-    private String attributeName;
-    private String attributeDefinition;
-    private String attributeWithoutFileDefinition;
-
-    /**
-     * The constructor of the task.
-     * @param info the control panel info.
-     * @param dlg the progress dialog that shows the progress of the task.
-     */
-    public NewAttributeTask(ControlPanelInfo info, ProgressDialog dlg)
-    {
-      super(info, dlg);
-      attributeName = getAttributeName();
-      attributeDefinition = attribute.toString();
-      AttributeType attr = getAttribute();
-      attr.setExtraProperty(ServerConstants.SCHEMA_PROPERTY_FILENAME,
-          (String)null);
-      attributeWithoutFileDefinition = attr.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Type getType()
-    {
-      return Type.NEW_ATTRIBUTE;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected CommonSchemaElements getSchemaElement()
-    {
-      if (attribute == null)
-      {
-        attribute = getAttribute();
-      }
-      return attribute;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Message getTaskDescription()
-    {
-      return INFO_CTRL_PANEL_NEW_ATTRIBUTE_TASK_DESCRIPTION.get(attributeName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected String getSchemaFileAttributeName()
-    {
-      return "attributeTypes";
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected String getSchemaFileAttributeValue()
-    {
-      if (isServerRunning())
-      {
-        return attributeDefinition;
-      }
-      else
-      {
-        return attributeWithoutFileDefinition;
-      }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void updateSchema() throws OpenDsException
-    {
-      SwingUtilities.invokeLater(new Runnable()
-      {
-        /**
-         * {@inheritDoc}
-         */
-        public void run()
-        {
-          printEquivalentCommandToAdd();
-          getProgressDialog().appendProgressHtml(
-              Utilities.getProgressWithPoints(
-                  INFO_CTRL_PANEL_CREATING_ATTRIBUTE_PROGRESS.get(
-                      attributeName),
-                  ColorAndFontConstants.progressFont));
-        }
-      });
-
-      if (isServerRunning())
-      {
-        try
-        {
-          BasicAttribute attr =
-            new BasicAttribute(getSchemaFileAttributeName());
-          attr.add(getSchemaFileAttributeValue());
-          ModificationItem mod = new ModificationItem(DirContext.ADD_ATTRIBUTE,
-              attr);
-          getInfo().getDirContext().modifyAttributes(
-              ConfigConstants.DN_DEFAULT_SCHEMA_ROOT,
-              new ModificationItem[]  { mod });
-        }
-        catch (NamingException ne)
-        {
-          throw new OnlineUpdateException(
-              ERR_CTRL_PANEL_ERROR_UPDATING_SCHEMA.get(ne.toString()), ne);
-        }
-      }
-      else
-      {
-        updateSchemaFile();
-      }
-      notifyConfigurationElementCreated(attribute);
-      SwingUtilities.invokeLater(new Runnable()
-      {
-        public void run()
-        {
-          getProgressDialog().appendProgressHtml(
-              Utilities.getProgressDone(ColorAndFontConstants.progressFont));
-        }
-      });
-    }
-
-    /**
-     * Updates the contents of the schema file.
-     * @throws OpenDsException if an error occurs updating the schema file.
-     */
-    private void updateSchemaFile() throws OpenDsException
-    {
-      if (isSchemaFileDefined)
-      {
-        LDIFExportConfig exportConfig =
-          new LDIFExportConfig(schemaFile,
-                               ExistingFileBehavior.OVERWRITE);
-        LDIFReader reader = null;
-        Entry schemaEntry = null;
-        try
-        {
-          reader = new LDIFReader(new LDIFImportConfig(schemaFile));
-          schemaEntry = reader.readEntry();
-
-          Modification mod = new Modification(ModificationType.ADD,
-              Attributes.create(getSchemaFileAttributeName().toLowerCase(),
-                  getSchemaFileAttributeValue()));
-          schemaEntry.applyModification(mod);
-          LDIFWriter writer = new LDIFWriter(exportConfig);
-          writer.writeEntry(schemaEntry);
-          exportConfig.getWriter().newLine();
-        }
-        catch (Throwable t)
-        {
-        }
-        finally
-        {
-          if (reader != null)
-          {
-            try
-            {
-              reader.close();
-            }
-            catch (Throwable t)
-            {
-            }
-          }
-          if (exportConfig != null)
-          {
-            try
-            {
-              exportConfig.close();
-            }
-            catch (Throwable t)
-            {
-            }
-          }
-        }
-      }
-      else
-      {
-        LDIFExportConfig exportConfig =
-          new LDIFExportConfig(schemaFile,
-                               ExistingFileBehavior.FAIL);
-        try
-        {
-          ArrayList<String> lines = getSchemaEntryLines();
-          for (String line : lines)
-          {
-            LDIFWriter.writeLDIFLine(new StringBuilder(line),
-                exportConfig.getWriter(), exportConfig.getWrapColumn() > 1,
-                exportConfig.getWrapColumn());
-          }
-          exportConfig.getWriter().newLine();
-        }
-        catch (Throwable t)
-        {
-          throw new OfflineUpdateException(
-              ERR_CTRL_PANEL_ERROR_UPDATING_SCHEMA.get(t.toString()), t);
-        }
-        finally
-        {
-          if (exportConfig != null)
-          {
-            try
-            {
-              exportConfig.close();
-            }
-            catch (Throwable t)
-            {
-            }
-          }
-        }
-      }
-    }
-  }
 }
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java
index a259816..193af06 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/NewObjectClassPanel.java
@@ -40,16 +40,13 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import javax.naming.NamingException;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.ModificationItem;
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
@@ -62,12 +59,11 @@
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
-import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
 import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
 import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
-import org.opends.guitools.controlpanel.task.OfflineUpdateException;
-import org.opends.guitools.controlpanel.task.OnlineUpdateException;
-import org.opends.guitools.controlpanel.task.SchemaTask;
+import org.opends.guitools.controlpanel.event.
+ ConfigurationElementCreatedListener;
+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;
@@ -78,20 +74,9 @@
 import org.opends.messages.MessageBuilder;
 import org.opends.server.config.ConfigConstants;
 import org.opends.server.types.AttributeType;
-import org.opends.server.types.Attributes;
-import org.opends.server.types.CommonSchemaElements;
-import org.opends.server.types.Entry;
-import org.opends.server.types.ExistingFileBehavior;
-import org.opends.server.types.LDIFExportConfig;
-import org.opends.server.types.LDIFImportConfig;
-import org.opends.server.types.Modification;
-import org.opends.server.types.ModificationType;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.types.ObjectClassType;
-import org.opends.server.types.OpenDsException;
 import org.opends.server.types.Schema;
-import org.opends.server.util.LDIFReader;
-import org.opends.server.util.LDIFWriter;
 import org.opends.server.util.ServerConstants;
 import org.opends.server.util.StaticUtils;
 
@@ -187,7 +172,24 @@
     final boolean[] repack = {firstSchema};
     final boolean[] error = {false};
 
-    if (s != null)
+    final boolean schemaChanged;
+    if (schema != null && s != null)
+    {
+      schemaChanged = !ServerDescriptor.areSchemasEqual(s, schema);
+    }
+    else if (schema == null && s != null)
+    {
+      schemaChanged = true;
+    }
+    else if (s == null && schema != null)
+    {
+      schemaChanged = false;
+    }
+    else
+    {
+      schemaChanged = false;
+    }
+    if (schemaChanged)
     {
       schema = s;
 
@@ -230,7 +232,10 @@
           {
             parent.setSelectedItem(schema.getObjectClass("top"));
           }
-          updateAttributes();
+          if (schemaChanged)
+          {
+            updateAttributes();
+          }
         }
         if (repack[0])
         {
@@ -332,14 +337,23 @@
         Utilities.createFrame(),
         Utilities.getParentDialog(this),
         INFO_CTRL_PANEL_NEW_OBJECTCLASS_PANEL_TITLE.get(), getInfo());
-    NewObjectClassTask newTask = null;
+    NewSchemaElementsTask newTask = null;
     if (errors.size() == 0)
     {
-      newTask = new NewObjectClassTask(getInfo(), dlg);
+      LinkedHashSet<AttributeType> attributes =
+        new LinkedHashSet<AttributeType>(1);
+      LinkedHashSet<ObjectClass> ocs = new LinkedHashSet<ObjectClass>();
+      ocs.add(getObjectClass());
+      newTask = new NewSchemaElementsTask(getInfo(), dlg, ocs, attributes);
       for (Task task : getInfo().getTasks())
       {
         task.canLaunch(newTask, errors);
       }
+      for (ConfigurationElementCreatedListener listener :
+        getConfigurationElementCreatedListeners())
+      {
+        newTask.addConfigurationElementCreatedListener(listener);
+      }
     }
     if (errors.size() == 0)
     {
@@ -712,13 +726,19 @@
     return al;
   }
 
+  private String getDescription()
+  {
+    return description.getText().trim();
+  }
+
   private ObjectClass getObjectClass()
   {
     ObjectClass oc = new ObjectClass("", getObjectClassName(), getAllNames(),
-        getOID(), description.getText().trim(),
+        getOID(),
+        getDescription(),
         getSuperior(),
         getRequiredAttributes(),
-        getAllowedAttributes(),
+        getOptionalAttributes(),
         getObjectClassType(),
         obsolete.isSelected(),
         getExtraProperties());
@@ -735,243 +755,19 @@
   {
     HashSet<AttributeType> attrs = new HashSet<AttributeType>();
     attrs.addAll(attributes.getSelectedListModel1().getData());
+    attrs.removeAll(inheritedRequiredAttributes);
     return attrs;
   }
 
-  private Set<AttributeType> getAllowedAttributes()
+  private Set<AttributeType> getOptionalAttributes()
   {
     HashSet<AttributeType> attrs = new HashSet<AttributeType>();
     attrs.addAll(attributes.getSelectedListModel2().getData());
+    attrs.removeAll(inheritedOptionalAttributes);
     return attrs;
   }
 
   /**
-   * The task in charge of creating the object class.
-   *
-   */
-  protected class NewObjectClassTask extends SchemaTask
-  {
-    private ObjectClass oc;
-    private String ocName;
-    private String ocDefinition;
-    private String ocWithoutFileDefinition;
-
-    /**
-     * The constructor of the task.
-     * @param info the control panel info.
-     * @param dlg the progress dialog that shows the progress of the task.
-     */
-    public NewObjectClassTask(ControlPanelInfo info, ProgressDialog dlg)
-    {
-      super(info, dlg);
-      ocName = getObjectClassName();
-      ocDefinition = getSchemaElement().toString();
-      ObjectClass oc = getObjectClass();
-      oc.setExtraProperty(ServerConstants.SCHEMA_PROPERTY_FILENAME,
-          (String)null);
-      ocWithoutFileDefinition = oc.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Type getType()
-    {
-      return Type.NEW_OBJECTCLASS;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected CommonSchemaElements getSchemaElement()
-    {
-      if (oc == null)
-      {
-        oc = getObjectClass();
-      }
-      return oc;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Message getTaskDescription()
-    {
-      return INFO_CTRL_PANEL_NEW_OBJECTCLASS_TASK_DESCRIPTION.get(ocName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected String getSchemaFileAttributeName()
-    {
-      return "objectClasses";
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected String getSchemaFileAttributeValue()
-    {
-      if (isServerRunning())
-      {
-        return ocDefinition;
-      }
-      else
-      {
-        return ocWithoutFileDefinition;
-      }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void updateSchema() throws OpenDsException
-    {
-      SwingUtilities.invokeLater(new Runnable()
-      {
-        /**
-         * {@inheritDoc}
-         */
-        public void run()
-        {
-          printEquivalentCommandToAdd();
-          getProgressDialog().appendProgressHtml(
-              Utilities.getProgressWithPoints(
-                  INFO_CTRL_PANEL_CREATING_OBJECTCLASS_PROGRESS.get(ocName),
-                  ColorAndFontConstants.progressFont));
-        }
-      });
-
-      if (isServerRunning())
-      {
-        try
-        {
-          BasicAttribute attr =
-            new BasicAttribute(getSchemaFileAttributeName());
-          attr.add(getSchemaFileAttributeValue());
-          ModificationItem mod = new ModificationItem(DirContext.ADD_ATTRIBUTE,
-              attr);
-          getInfo().getDirContext().modifyAttributes(
-              ConfigConstants.DN_DEFAULT_SCHEMA_ROOT,
-              new ModificationItem[]  { mod });
-        }
-        catch (NamingException ne)
-        {
-          throw new OnlineUpdateException(
-              ERR_CTRL_PANEL_ERROR_UPDATING_SCHEMA.get(ne.toString()), ne);
-        }
-      }
-      else
-      {
-        updateSchemaFile();
-      }
-      notifyConfigurationElementCreated(oc);
-      SwingUtilities.invokeLater(new Runnable()
-      {
-        /**
-         * {@inheritDoc}
-         */
-        public void run()
-        {
-          getProgressDialog().appendProgressHtml(
-              Utilities.getProgressDone(ColorAndFontConstants.progressFont));
-        }
-      });
-    }
-
-    /**
-     * Updates the contents of the schema file.
-     * @throws OpenDsException if an error occurs updating the schema file.
-     */
-    private void updateSchemaFile() throws OpenDsException
-    {
-      if (isSchemaFileDefined)
-      {
-        LDIFExportConfig exportConfig =
-          new LDIFExportConfig(schemaFile,
-                               ExistingFileBehavior.OVERWRITE);
-        LDIFReader reader = null;
-        Entry schemaEntry = null;
-        try
-        {
-          reader = new LDIFReader(new LDIFImportConfig(schemaFile));
-          schemaEntry = reader.readEntry();
-
-          Modification mod = new Modification(ModificationType.ADD,
-              Attributes.create(getSchemaFileAttributeName().toLowerCase(),
-                  getSchemaFileAttributeValue()));
-          schemaEntry.applyModification(mod);
-          LDIFWriter writer = new LDIFWriter(exportConfig);
-          writer.writeEntry(schemaEntry);
-          exportConfig.getWriter().newLine();
-        }
-        catch (Throwable t)
-        {
-        }
-        finally
-        {
-          if (reader != null)
-          {
-            try
-            {
-              reader.close();
-            }
-            catch (Throwable t)
-            {
-            }
-          }
-          if (exportConfig != null)
-          {
-            try
-            {
-              exportConfig.close();
-            }
-            catch (Throwable t)
-            {
-            }
-          }
-        }
-      }
-      else
-      {
-        LDIFExportConfig exportConfig =
-          new LDIFExportConfig(schemaFile,
-                               ExistingFileBehavior.FAIL);
-        try
-        {
-          ArrayList<String> lines = getSchemaEntryLines();
-          for (String line : lines)
-          {
-            LDIFWriter.writeLDIFLine(new StringBuilder(line),
-                exportConfig.getWriter(), exportConfig.getWrapColumn() > 1,
-                exportConfig.getWrapColumn());
-          }
-          exportConfig.getWriter().newLine();
-        }
-        catch (Throwable t)
-        {
-          throw new OfflineUpdateException(
-              ERR_CTRL_PANEL_ERROR_UPDATING_SCHEMA.get(t.toString()), t);
-        }
-        finally
-        {
-          if (exportConfig != null)
-          {
-            try
-            {
-              exportConfig.close();
-            }
-            catch (Throwable t)
-            {
-            }
-          }
-        }
-      }
-    }
-  }
-
-  /**
    * A renderer for the attribute lists.  The renderer basically marks the
    * inherited attributes with an asterisk.
    *
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/SchemaBrowserRightPanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/SchemaBrowserRightPanel.java
index 09528ab..7899656 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/SchemaBrowserRightPanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/SchemaBrowserRightPanel.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 package org.opends.guitools.controlpanel.ui;
@@ -37,6 +37,8 @@
 
 import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
 import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
+import org.opends.guitools.controlpanel.event.
+ ConfigurationElementCreatedListener;
 import org.opends.guitools.controlpanel.event.SchemaElementSelectionListener;
 import org.opends.guitools.controlpanel.util.Utilities;
 import org.opends.messages.Message;
@@ -74,8 +76,9 @@
 
   private final SchemaElementPanel[] panels =
   {   standardObjectClassPanel, configurationObjectClassPanel,
-      customObjectClassPanel, standardAttributePanel,
-      configurationAttributePanel, customAttributePanel, matchingRulePanel,
+      customObjectClassPanel,
+      standardAttributePanel, configurationAttributePanel, customAttributePanel,
+      matchingRulePanel,
       attributeSyntaxPanel
   };
 
@@ -145,6 +148,34 @@
   }
 
   /**
+   * Adds a configuration element created listener.
+   * @param listener the listener.
+   */
+  public void addConfigurationElementCreatedListener(
+      ConfigurationElementCreatedListener listener)
+  {
+    super.addConfigurationElementCreatedListener(listener);
+    for (SchemaElementPanel panel : panels)
+    {
+      panel.addConfigurationElementCreatedListener(listener);
+    }
+  }
+
+  /**
+   * Removes a configuration element created listener.
+   * @param listener the listener.
+   */
+  public void removeConfigurationElementCreatedListener(
+      ConfigurationElementCreatedListener listener)
+  {
+    super.removeConfigurationElementCreatedListener(listener);
+    for (SchemaElementPanel panel : panels)
+    {
+      panel.removeConfigurationElementCreatedListener(listener);
+    }
+  }
+
+  /**
    * Updates the contents of the panel with the provided standard object class.
    * @param oc the object class.
    * @param schema the schema.
@@ -242,7 +273,7 @@
    * @param syntax the attribute syntax.
    * @param schema the schema.
    */
-  public void updateAttributeSyntax(AttributeSyntax syntax, Schema schema)
+  public void updateAttributeSyntax(AttributeSyntax<?> syntax, Schema schema)
   {
     attributeSyntaxPanel.update(syntax, schema);
     schemaElementPanel = attributeSyntaxPanel;
@@ -348,9 +379,9 @@
 
   /**
    * Tells whether the user chose to save the changes in the panel, to not save
-   * them or simply cancelled the selection in the tree.
+   * them or simply canceled the selection in the tree.
    * @return the value telling whether the user chose to save the changes in the
-   * panel, to not save them or simply cancelled the selection in the tree.
+   * panel, to not save them or simply canceled the selection in the tree.
    */
   public UnsavedChangesDialog.Result checkUnsavedChanges()
   {
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
index 9f5c9cd..8a5a4f5 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
@@ -47,6 +47,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -55,6 +56,8 @@
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.naming.NamingEnumeration;
 import javax.naming.directory.SearchControls;
@@ -143,6 +146,9 @@
   private static final String MAIN_PANEL = "mainPanel";
   private static final String MESSAGE_PANEL = "messagePanel";
 
+  private static final Logger LOG =
+    Logger.getLogger(StatusGenericPanel.class.getName());
+
   /**
    * The error pane.
    */
@@ -538,7 +544,7 @@
   public void addConfigurationElementCreatedListener(
       ConfigurationElementCreatedListener listener)
   {
-    confListeners.add(listener);
+    getConfigurationElementCreatedListeners().add(listener);
   }
 
   /**
@@ -548,7 +554,7 @@
   public void removeConfigurationElementCreatedListener(
       ConfigurationElementCreatedListener listener)
   {
-    confListeners.remove(listener);
+    getConfigurationElementCreatedListeners().remove(listener);
   }
 
   /**
@@ -558,7 +564,8 @@
    */
   protected void notifyConfigurationElementCreated(Object configObject)
   {
-    for (ConfigurationElementCreatedListener listener : confListeners)
+    for (ConfigurationElementCreatedListener listener :
+      getConfigurationElementCreatedListeners())
     {
       listener.elementCreated(
           new ConfigurationElementCreatedEvent(this, configObject));
@@ -566,6 +573,16 @@
   }
 
   /**
+   * Returns the list of configuration listeners.
+   * @return the list of configuration listeners.
+   */
+  protected List<ConfigurationElementCreatedListener>
+  getConfigurationElementCreatedListeners()
+  {
+    return confListeners;
+  }
+
+  /**
    * Notification that cancel was clicked, the panel is in charge
    * of doing whatever is required (close the dialog, etc.).
    *
@@ -1404,6 +1421,20 @@
   protected void updateComboBoxModel(final Collection<?> newElements,
       final DefaultComboBoxModel model)
   {
+    updateComboBoxModel(newElements, model, null);
+  }
+
+  /**
+   * Updates a combo box model with a number of items.
+   * @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.
+   */
+  protected void updateComboBoxModel(final Collection<?> newElements,
+      final DefaultComboBoxModel model,
+      final Comparator<Object> comparator)
+  {
     SwingUtilities.invokeLater(new Runnable()
     {
       public void run()
@@ -1414,7 +1445,15 @@
           int i = 0;
           for (Object newElement : newElements)
           {
-            changed = !newElement.equals(model.getElementAt(i));
+            if (comparator == null)
+            {
+              changed = !newElement.equals(model.getElementAt(i));
+            }
+            else
+            {
+              changed =
+                comparator.compare(newElement, model.getElementAt(i)) != 0;
+            }
             if (changed)
             {
               break;
@@ -1799,6 +1838,7 @@
 
           if (t != null)
           {
+            LOG.log(Level.WARNING, "Error occurred running task: "+t, t);
             if ((task.getReturnCode() != null) &&
                 (errorDetailCode != null))
             {
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/ControlPanelLog.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/ControlPanelLog.java
index 84e679b..1a21d6f 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/ControlPanelLog.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/ControlPanelLog.java
@@ -61,7 +61,7 @@
       for (String packageName : packages)
       {
         Logger logger = Logger.getLogger(packageName);
-        logger.setUseParentHandlers(false); // disable logging to console
+        //logger.setUseParentHandlers(false); // disable logging to console
         logger.addHandler(fileHandler);
       }
       Logger logger = Logger.getLogger(packages[0]);
@@ -78,7 +78,7 @@
    */
   static public void initPackage(String packageName) throws IOException {
     Logger logger = Logger.getLogger(packageName);
-    logger.setUseParentHandlers(false); // disable logging to console
+    //logger.setUseParentHandlers(false); // disable logging to console
     logger.addHandler(fileHandler);
     logger.log(Level.INFO, getInitialLogRecord());
   }
diff --git a/opendj-sdk/opends/src/messages/messages/admin_tool.properties b/opendj-sdk/opends/src/messages/messages/admin_tool.properties
index eb26bc8..e054abd 100644
--- a/opendj-sdk/opends/src/messages/messages/admin_tool.properties
+++ b/opendj-sdk/opends/src/messages/messages/admin_tool.properties
@@ -1104,6 +1104,8 @@
 INFO_CTRL_PANEL_DELETING_INDEX=Deleting index '%s'
 INFO_CTRL_PANEL_DELETING_VLV_INDEX=Deleting VLV index '%s'
 
+INFO_CTRL_PANEL_CONFIRMATION_DELETE_SCHEMA_ELEMENTS_MSG=Are you sure you want \
+ to delete the elements '%s' defined in the schema?
 INFO_CTRL_PANEL_DELETE_SCHEMA_ELEMENT_TASK_DESCRIPTION=Delete schema elements.
 INFO_CTRL_PANEL_DELETING_OBJECTCLASS=Deleting objectclass '%s'
 INFO_CTRL_PANEL_DELETING_ATTRIBUTE=Deleting attribute '%s'
@@ -1113,11 +1115,16 @@
  configuration.  Details: %s
 MILD_ERR_CTRL_PANEL_ERROR_CHECKING_ENTRY=Error checking entry.  Details: %s
 
-INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_SCHEMA_ELEMENT_OFFLINE=This operation \
- is equivalent to removing the following attribute from the schema definition \
- entry (cn=schema) in file '%s':
-INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_SCHEMA_ELEMENT_ONLINE=Equivalent \
-command line to update the schema:
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_ATTRIBUTE_OFFLINE=Deleting attribute \
+ '%s' can also be done removing the following attribute from the schema \
+ definition entry (cn=schema) in file '%s':
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_OBJECTCLASS_OFFLINE=Deleting object \
+ class '%s' can also be done removing the following attribute from the schema \
+ definition entry (cn=schema) in file '%s':
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_ATTRIBUTE_ONLINE=Equivalent \
+command line to delete attribute '%s':
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_DELETE_OBJECTCLASS_ONLINE=Equivalent \
+command line to delete object class '%s':
 INFO_CTRL_PANEL_MODIFY_ENTRY_TASK_DESCRIPTION=Modify entry '%s'.
 INFO_CTRL_PANEL_RENAMING_ENTRY=Renaming entry '%s' to '%s'
 INFO_CTRL_PANEL_MODIFYING_ENTRY=Modifying entry '%s'
@@ -1152,14 +1159,15 @@
 INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_START_SERVER=Equivalent command line to \
  start the server:
 INFO_CTRL_PANEL_SERVER_STOPPED=Server Stopped
-INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ELEMENT_OFFLINE=This operation is \
- equivalent to adding the following attribute to the schema definition entry \
- (cn=schema) in file '%s':
-INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ENTRY_OFFLINE=This operation is \
- equivalent to adding the following entry to the file '%s':
-INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ELEMENT_ONLINE=Equivalent command \
- line to update the schema:
-
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ENTRY_OFFLINE=Adding the schema \
+ elements '%s' can also be done adding the following entry to the file '%s':
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_SCHEMA_ELEMENT_OFFLINE=Adding the schema \
+ elements '%s' can also be done adding the following attributes to the \
+ schema definition entry (cn=schema) in file '%s':
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_ATTRIBUTE_ONLINE=Equivalent \
+command line to add attribute '%s':
+INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_ADD_OBJECTCLASS_ONLINE=Equivalent \
+command line to add object class '%s':
 MILD_ERR_CTRL_PANEL_BACKEND_NOT_FOUND_SUMMARY=Could not find backend
 MILD_ERR_CTRL_PANEL_BACKEND_NOT_FOUND_DETAILS=The backend '%s' could not be \
  found.  Check main panel for more information.
@@ -1608,7 +1616,7 @@
 
 INFO_CTRL_PANEL_SCHEMA_ELEMENT_NAME=Name
 INFO_CTRL_PANEL_SCHEMA_ELEMENT_TYPE=Type
-INFO_CTRL_PANEL_PARENT_CLASS=Parent Class
+INFO_CTRL_PANEL_PARENT_CLASS=Superior Class
 INFO_CTRL_PANEL_CHILD_CLASS=Child Class
 INFO_CTRL_PANEL_REQUIRED_ATTRIBUTES=Required Attributes
 INFO_CTRL_PANEL_OPTIONAL_ATTRIBUTES=Optional Attributes
@@ -1618,25 +1626,29 @@
 INFO_CTRL_PANEL_CATEGORY_ITEM_SELECTED=Category Item Selected
 INFO_CTRL_PANEL_MULTIPLE_SCHEMA_ITEMS_SELECTED=Multiple Schema Items Selected
 
-MILD_ERR_CANNOT_DELETE_PARENT_OBJECTCLASS=ObjectClass '%s' is superior of the \
- following classes: %s.  You must redefine these classes so that they do not \
- inherit from objectClass '%s' before deleting it.
-MILD_ERR_CANNOT_DELETE_PARENT_ATTRIBUTE=Attribute '%s' is superior of the \
- following attributes: %s.  You must redefine these attributes so that they do \
- not inherit from attribute '%s' before deleting it.
-MILD_ERR_CANNOT_DELETE_ATTRIBUTE_WITH_DEPENDENCIES=Attribute '%s' is optional \
- or required by the following objectClasses: %s.  You must redefine these \
- classes so that they do not depend on attribute '%s' before deleting it.
-MILD_ERR_CANNOT_MODIFY_PARENT_ATTRIBUTE=Attribute '%s' is superior of the \
- following attributes: %s.  You must redefine these attributes so that they do \
- not inherit from attribute '%s' before modifying it.
+INFO_OBJECTCLASS_IS_SUPERIOR=Object class '%s' is superior of the \
+ following object classes: %s.  If you continue, these object classes will be \
+ updated with a new superior.
+INFO_OBJECTCLASSES_ARE_SUPERIOR=The selected object classes are superior of \
+ the following object classes: %s.  If you continue, these object classes will \
+ be updated with a new superior.
+INFO_ATTRIBUTE_IS_SUPERIOR=Attribute '%s' is superior of the \
+ following attributes: %s.  If you continue, these attributes will be updated \
+ with a new superior.
+INFO_ATTRIBUTES_ARE_SUPERIOR=The selected attributes are superior of the \
+ following attributes: %s.  If you continue, these attributes will be updated \
+ with a new superior.
+INFO_ATTRIBUTE_WITH_DEPENDENCIES=Attribute '%s' is optional or required by the \
+ following object classes: %s.  If you continue, the definition of the object \
+ classes will be modified.
+INFO_ATTRIBUTES_WITH_DEPENDENCIES=The selected attributes are optional or \
+ required by the following object classes: %s.  If you continue, the \
+ definition of the object classes will be modified.
 INFO_CTRL_PANEL_MANAGE_SCHEMA_TITLE=Manage Schema
 INFO_CTRL_PANEL_DELETE_OBJECTCLASSES_TITLE=Delete Objectclasses
 INFO_CTRL_PANEL_DELETE_ATTRIBUTES_TITLE=Delete Attributes
 INFO_CTRL_PANEL_DELETE_OBJECTCLASSES_AND_ATTRIBUTES_TITLE=Delete Objectclasses \
  and Attributes
-INFO_CTRL_PANEL_CONFIRMATION_DELETE_SCHEMA_ELEMENTS_DETAILS=Are you sure you \
- want to delete the elements '%s' defined in the schema?
 INFO_CTRL_PANEL_DELETING_SCHEMA_ELEMENTS_SUMMARY=Deleting...
 INFO_CTRL_PANEL_DELETING_SCHEMA_ELEMENTS_COMPLETE=Schema Definitions Deleted
 INFO_CTRL_PANEL_DELETING_SCHEMA_ELEMENTS_SUCCESSFUL=The schema elements '%s' \
@@ -1653,6 +1665,7 @@
 
 INFO_CTRL_PANEL_DELETE_ATTRIBUTE_BUTTON=Delete Attribute...
 INFO_CTRL_PANEL_DELETE_ATTRIBUTE_TITLE=Delete Attribute
+INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TITLE=Modify Attribute
 INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_ATTRIBUTE_DELETE=The server is \
  running.  You must provide authentication to delete the attribute.
 INFO_CTRL_PANEL_CONFIRMATION_DELETE_ATTRIBUTE_DETAILS=Are you sure you want to \
@@ -1663,13 +1676,30 @@
  successfully deleted
 MILD_ERR_CTRL_PANEL_DELETING_ATTRIBUTE_ERROR_SUMMARY=Error deleting \
  attribute
-MILD_ERR_CTRL_PANEL_DELETING_ATTRIBUTE_ERROR_DETAILS=An error occurred deleting \
- attribute '%s'.  Check details for more information.
+MILD_ERR_CTRL_PANEL_DELETING_ATTRIBUTE_ERROR_DETAILS=An error occurred \
+ deleting attribute '%s'.  Check details for more information.
+INFO_CTRL_PANEL_MODIFYING_ATTRIBUTE_SUMMARY=Modifying attribute '%s'...
+INFO_CTRL_PANEL_MODIFYING_ATTRIBUTE_COMPLETE=Attribute Modified
+INFO_CTRL_PANEL_MODIFYING_ATTRIBUTE_SUCCESSFUL=The attribute '%s' was \
+ successfully modified
+MILD_ERR_CTRL_PANEL_MODIFYING_ATTRIBUTE_ERROR_SUMMARY=Error modifying \
+ attribute
+MILD_ERR_CTRL_PANEL_MODIFYING_ATTRIBUTE_ERROR_DETAILS=An error occurred \
+ modifying attribute '%s'.  Check details for more information.
+
+INFO_CTRL_PANEL_MODIFYING_OBJECTCLASS_SUMMARY=Modifying object class '%s'...
+INFO_CTRL_PANEL_MODIFYING_OBJECTCLASS_COMPLETE=Object Class Modified
+INFO_CTRL_PANEL_MODIFYING_OBJECTCLASS_SUCCESSFUL=The object class '%s' was \
+ successfully modified
+MILD_ERR_CTRL_PANEL_MODIFYING_OBJECTCLASS_ERROR_SUMMARY=Error modifying \
+ object class
+MILD_ERR_CTRL_PANEL_MODIFYING_OBJECTCLASS_ERROR_DETAILS=An error occurred \
+ modifying object class '%s'.  Check details for more information.
 
 INFO_CTRL_PANEL_DELETE_OBJECTCLASS_BUTTON=Delete Object Class...
 INFO_CTRL_PANEL_DELETE_OBJECTCLASS_TITLE=Delete Object Class
-INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_OBJECTCLASS_DELETE=The server is \
- running.  You must provide authentication to delete the object class.
+INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_OBJECTCLASS_EDIT=The server is \
+ running.  You must provide authentication to edit the object class.
 INFO_CTRL_PANEL_CONFIRMATION_DELETE_OBJECTCLASS_DETAILS=Are you sure you want \
  to delete the object class '%s' defined in the schema?
 INFO_CTRL_PANEL_DELETING_OBJECTCLASS_SUMMARY=Deleting object class '%s'...
@@ -2073,7 +2103,19 @@
 MILD_ERR_CTRL_PANEL_EMPTY_ALIAS=You have provided an empty alias.
 MILD_ERR_CTRL_PANEL_ALIAS_ALREADY_IN_USE=The provided alias '%s' \
  already exists in the schema (defined as %s).
+MILD_ERR_NON_MODIFIABLE_CANNOT_BE_USER_APPLICATIONS=Non Modifiable attributes \
+ must have an operational usage.
+MILD_ERR_CTRL_PANEL_ATTRIBUTE_CANNOT_BE_ITS_SUPERIOR=An attribute cannot be \
+ its own superior.
+MILD_ERR_CTRL_PANEL_OBJECTCLASS_CANNOT_BE_ITS_SUPERIOR=An object class cannot \
+ be its own superior.
+MILD_ERR_CTRL_PANEL_OBJECTCLASS_IS_SUPERIOR_OF_SUPERIOR=The object class is \
+ superior (directly or indirectly) of '%s'.
+MILD_ERR_CTRL_PANEL_ATTRIBUTE_IS_SUPERIOR_OF_SUPERIOR=The attribute is \
+ superior (directly or indirectly) of '%s'.
 INFO_CTRL_PANEL_CREATING_ATTRIBUTE_SUMMARY=Creating attribute '%s'...
+INFO_CTRL_PANEL_UPDATING_SCHEMA_FILE_PROGRESS=Adding schema elements to schema \
+ file '%s'...
 INFO_CTRL_PANEL_CREATING_ATTRIBUTE_COMPLETE=Attribute created in schema
 INFO_CTRL_PANEL_CREATING_ATTRIBUTE_SUCCESSFUL=The attribute '%s' was \
  successfully created.
@@ -2104,9 +2146,28 @@
 INFO_CTRL_PANEL_DEFAULT_DEFINED_IN_SYNTAX=- Default defined in syntax (%s) -
 INFO_CTRL_PANEL_NEW_ATTRIBUTE_TASK_DESCRIPTION=Create new attribute '%s' in \
  schema.
+INFO_CTRL_PANEL_NEW_ATTRIBUTES_TASK_DESCRIPTION=Creating new attributes '%s' \
+ in schema.
+INFO_CTRL_PANEL_NEW_OBJECTCLASSES_TASK_DESCRIPTION=Creating new object classes \
+ '%s' in schema.
+INFO_CTRL_PANEL_NEW_SCHEMA_ELEMENTS_TASK_DESCRIPTION=Creating attributes '%s' \
+ and object classes '%s' in schema.
+INFO_CTRL_PANEL_EXPLANATION_TO_MODIFY_ATTRIBUTE=To modify attribute '%s' it \
+ will be deleted and then recreated.  The same applies to all the schema \
+ elements that have references to it.
+INFO_CTRL_PANEL_EXPLANATION_TO_MODIFY_OBJECTCLASS=To modify object class '%s' \
+ it will be deleted and then recreated.  The same applies to all the schema \
+ elements that have references to it.
+INFO_CTRL_PANEL_EXPLANATION_TO_DELETE_REFERENCED_ELEMENTS=To modify \
+ references to the deleted attributes and object classes the schema elements \
+ that refer to them must be deleted and then added again.
 INFO_CTRL_PANEL_CREATING_ATTRIBUTE_PROGRESS=Creating attribute '%s'
+INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TASK_DESCRIPTION=Modify attribute '%s' in \
+ schema
+INFO_CTRL_PANEL_MODIFY_OBJECTCLASS_TASK_DESCRIPTION=Modify object class '%s' \
+ in schema
 INFO_CTRL_PANEL_ATTRIBUTE_NAME_LABEL=Name:
-INFO_CTRL_PANEL_ATTRIBUTE_PARENT_LABEL=Parent:
+INFO_CTRL_PANEL_ATTRIBUTE_PARENT_LABEL=Superior:
 INFO_CTRL_PANEL_ATTRIBUTE_OID_LABEL=OID:
 INFO_CTRL_PANEL_ATTRIBUTE_ALIASES_LABEL=Aliases:
 INFO_CTRL_PANEL_ATTRIBUTE_ORIGIN_LABEL=Origin:
@@ -2274,7 +2335,7 @@
  in schema.
 INFO_CTRL_PANEL_CREATING_OBJECTCLASS_PROGRESS=Creating object class '%s'
 INFO_CTRL_PANEL_OBJECTCLASS_NAME_LABEL=Name:
-INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL=Parent:
+INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL=Superior:
 INFO_CTRL_PANEL_OBJECTCLASS_OID_LABEL=OID:
 INFO_CTRL_PANEL_OBJECTCLASS_ALIASES_LABEL=Aliases:
 INFO_CTRL_PANEL_OBJECTCLASS_ORIGIN_LABEL=Origin:

--
Gitblit v1.10.0