From 02805157fa504b3dbf701a62280ca9aaf82183b5 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Wed, 05 Sep 2007 20:12:11 +0000
Subject: [PATCH] Partial fix for issue 1449: administration framework aggregation support

---
 opends/src/server/org/opends/server/admin/client/ldap/LDAPDriver.java |  144 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 112 insertions(+), 32 deletions(-)

diff --git a/opends/src/server/org/opends/server/admin/client/ldap/LDAPDriver.java b/opends/src/server/org/opends/server/admin/client/ldap/LDAPDriver.java
index eaa99ab..668d495 100644
--- a/opends/src/server/org/opends/server/admin/client/ldap/LDAPDriver.java
+++ b/opends/src/server/org/opends/server/admin/client/ldap/LDAPDriver.java
@@ -49,6 +49,7 @@
 
 import org.opends.messages.Message;
 import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AggregationPropertyDefinition;
 import org.opends.server.admin.Configuration;
 import org.opends.server.admin.ConfigurationClient;
 import org.opends.server.admin.DefaultBehaviorException;
@@ -61,11 +62,14 @@
 import org.opends.server.admin.ManagedObjectNotFoundException;
 import org.opends.server.admin.ManagedObjectPath;
 import org.opends.server.admin.PropertyDefinition;
+import org.opends.server.admin.PropertyDefinitionVisitor;
 import org.opends.server.admin.PropertyException;
 import org.opends.server.admin.PropertyIsMandatoryException;
 import org.opends.server.admin.PropertyIsSingleValuedException;
 import org.opends.server.admin.PropertyOption;
+import org.opends.server.admin.Reference;
 import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.UnknownPropertyDefinitionException;
 import org.opends.server.admin.DefinitionDecodingException.Reason;
 import org.opends.server.admin.client.AuthorizationException;
 import org.opends.server.admin.client.CommunicationException;
@@ -84,6 +88,73 @@
  */
 final class LDAPDriver extends Driver {
 
+  /**
+   * A visitor which is used to decode property LDAP values.
+   */
+  private static final class ValueDecoder extends
+      PropertyDefinitionVisitor<Object, String> {
+
+    /**
+     * Decodes the provided property LDAP value.
+     *
+     * @param <PD>
+     *          The type of the property.
+     * @param pd
+     *          The property definition.
+     * @param value
+     *          The LDAP string representation.
+     * @return Returns the decoded LDAP value.
+     * @throws IllegalPropertyValueStringException
+     *           If the property value could not be decoded because it
+     *           was invalid.
+     */
+    public static <PD> PD decode(PropertyDefinition<PD> pd, Object value)
+        throws IllegalPropertyValueStringException {
+      String s = String.valueOf(value);
+      return pd.castValue(pd.accept(new ValueDecoder(), s));
+    }
+
+
+
+    // Prevent instantiation.
+    private ValueDecoder() {
+      // No implementation required.
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public <C extends ConfigurationClient, S extends Configuration>
+    Object visitAggregation(AggregationPropertyDefinition<C, S> d, String p) {
+      // Aggregations values are stored as full DNs in LDAP, but
+      // just their common name is exposed in the admin framework.
+      try {
+        Reference<C, S> reference = Reference.parseDN(d.getParentPath(), d
+            .getRelationDefinition(), p);
+        return reference.getName();
+      } catch (IllegalArgumentException e) {
+        throw new IllegalPropertyValueStringException(d, p);
+      }
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public <T> Object visitUnknown(PropertyDefinition<T> d, String p)
+        throws UnknownPropertyDefinitionException {
+      // By default the property definition's decoder will do.
+      return d.decodeValue(p);
+    }
+  }
+
+
+
   // The LDAP connection.
   private final LDAPConnection connection;
 
@@ -151,20 +222,8 @@
       for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
         String attrID = profile.getAttributeName(mod, pd);
         Attribute attribute = attributes.get(attrID);
-        List<String> values = new LinkedList<String>();
-
-        if (attribute != null && attribute.size() != 0) {
-          NamingEnumeration<?> ldapValues = attribute.getAll();
-          while (ldapValues.hasMore()) {
-            Object obj = ldapValues.next();
-            if (obj != null) {
-              values.add(obj.toString());
-            }
-          }
-        }
-
         try {
-          decodeProperty(newProperties, path, pd, values);
+          decodeProperty(newProperties, path, pd, attribute);
         } catch (PropertyException e) {
           exceptions.add(e);
         }
@@ -193,12 +252,23 @@
   /**
    * {@inheritDoc}
    */
+  @SuppressWarnings("unchecked")
   @Override
-  public <PD> SortedSet<PD> getPropertyValues(ManagedObjectPath<?, ?> path,
+  public <C extends ConfigurationClient, S extends Configuration, PD>
+  SortedSet<PD> getPropertyValues(ManagedObjectPath<C, S> path,
       PropertyDefinition<PD> pd) throws IllegalArgumentException,
       DefinitionDecodingException, AuthorizationException,
       ManagedObjectNotFoundException, CommunicationException,
       PropertyException {
+    // Check that the requested property is from the definition
+    // associated with the path.
+    AbstractManagedObjectDefinition<C, S> d = path.getManagedObjectDefinition();
+    PropertyDefinition<?> tmp = d.getPropertyDefinition(pd.getName());
+    if (tmp != pd) {
+      throw new IllegalArgumentException("The property " + pd.getName()
+          + " is not associated with a " + d.getName());
+    }
+
     if (!managedObjectExists(path)) {
       throw new ManagedObjectNotFoundException();
     }
@@ -206,26 +276,27 @@
     try {
       // Read the entry associated with the managed object.
       LdapName dn = LDAPNameBuilder.create(path, profile);
-      AbstractManagedObjectDefinition<?, ?> d = path
-          .getManagedObjectDefinition();
-      ManagedObjectDefinition<?, ?> mod = getEntryDefinition(d, dn);
+      ManagedObjectDefinition<? extends C, ? extends S> mod;
+      mod = getEntryDefinition(d, dn);
+
+      // Make sure we use the correct property definition, the
+      // provided one might have been overridden in the resolved
+      // definition.
+      pd = (PropertyDefinition<PD>) mod.getPropertyDefinition(pd.getName());
 
       String attrID = profile.getAttributeName(mod, pd);
       Attributes attributes = connection.readEntry(dn, Collections
           .singleton(attrID));
       Attribute attribute = attributes.get(attrID);
 
+      // Decode the values.
       SortedSet<PD> values = new TreeSet<PD>(pd);
-      if (attribute == null || attribute.size() == 0) {
-        // Use the property's default values.
-        values.addAll(findDefaultValues(path, pd, false));
-      } else {
-        // Decode the values.
+      if (attribute != null) {
         NamingEnumeration<?> ldapValues = attribute.getAll();
         while (ldapValues.hasMore()) {
           Object obj = ldapValues.next();
           if (obj != null) {
-            PD value = pd.decodeValue(obj.toString());
+            PD value = ValueDecoder.decode(pd, obj);
             values.add(value);
           }
         }
@@ -240,6 +311,11 @@
         throw new PropertyIsMandatoryException(pd);
       }
 
+      if (values.isEmpty()) {
+        // Use the property's default values.
+        values.addAll(findDefaultValues(path.asSubType(mod), pd, false));
+      }
+
       return values;
     } catch (NameNotFoundException e) {
       throw new ManagedObjectNotFoundException();
@@ -471,24 +547,28 @@
 
   // Create a property using the provided string values.
   private <PD> void decodeProperty(PropertySet newProperties,
-      ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd, List<String> values)
-      throws PropertyException {
+      ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd,
+      Attribute attribute) throws PropertyException,
+      NamingException {
     PropertyException exception = null;
 
     // Get the property's active values.
-    Collection<PD> activeValues = new ArrayList<PD>(values.size());
-    for (String value : values) {
-      try {
-        activeValues.add(pd.decodeValue(value));
-      } catch (IllegalPropertyValueStringException e) {
-        exception = e;
+    SortedSet<PD> activeValues = new TreeSet<PD>(pd);
+    if (attribute != null) {
+      NamingEnumeration<?> ldapValues = attribute.getAll();
+      while (ldapValues.hasMore()) {
+        Object obj = ldapValues.next();
+        if (obj != null) {
+          PD value = ValueDecoder.decode(pd, obj);
+          activeValues.add(value);
+        }
       }
     }
 
     if (activeValues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
       // This exception takes precedence over previous exceptions.
       exception = new PropertyIsSingleValuedException(pd);
-      PD value = activeValues.iterator().next();
+      PD value = activeValues.first();
       activeValues.clear();
       activeValues.add(value);
     }

--
Gitblit v1.10.0