From 1df4f51adf614210ca4a9b9728327090ec5ea264 Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Fri, 11 Sep 2015 20:33:53 +0000
Subject: [PATCH] OPENDJ-1666 PR-19 CREST-3.0.0 Migration

---
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java |  269 ++++++++++++++++++++++-------------------------------
 1 files changed, 114 insertions(+), 155 deletions(-)

diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
index 3e7803e..dcf269f 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
@@ -21,7 +21,6 @@
 import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
 import static org.forgerock.opendj.rest2ldap.Utils.i18n;
 import static org.forgerock.opendj.rest2ldap.Utils.isNullOrEmpty;
-import static org.forgerock.opendj.rest2ldap.Utils.transform;
 import static org.forgerock.opendj.rest2ldap.WritabilityPolicy.READ_WRITE;
 
 import java.util.ArrayList;
@@ -29,13 +28,12 @@
 import java.util.List;
 import java.util.Set;
 
-import org.forgerock.json.fluent.JsonPointer;
-import org.forgerock.json.fluent.JsonValue;
+import org.forgerock.json.JsonPointer;
+import org.forgerock.json.JsonValue;
 import org.forgerock.json.resource.BadRequestException;
 import org.forgerock.json.resource.NotSupportedException;
 import org.forgerock.json.resource.PatchOperation;
 import org.forgerock.json.resource.ResourceException;
-import org.forgerock.json.resource.ResultHandler;
 import org.forgerock.opendj.ldap.Attribute;
 import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.Entry;
@@ -43,14 +41,14 @@
 import org.forgerock.opendj.ldap.Modification;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.util.Function;
-import org.forgerock.util.promise.NeverThrowsException;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.Promises;
 
 /**
  * An abstract LDAP attribute mapper which provides a simple mapping from a JSON
  * value to a single LDAP attribute.
  */
-abstract class AbstractLDAPAttributeMapper<T extends AbstractLDAPAttributeMapper<T>> extends
-        AttributeMapper {
+abstract class AbstractLDAPAttributeMapper<T extends AbstractLDAPAttributeMapper<T>> extends AttributeMapper {
     List<Object> defaultJSONValues = emptyList();
     final AttributeDescription ldapAttributeName;
     private boolean isRequired;
@@ -101,25 +99,45 @@
     }
 
     @Override
-    void create(final Context c, final JsonPointer path, final JsonValue v,
-            final ResultHandler<List<Attribute>> h) {
-        getNewLDAPAttributes(c, path, v, createAttributeHandler(path, h));
+    Promise<List<Attribute>, ResourceException> create(
+            final RequestState requestState, final JsonPointer path, final JsonValue v) {
+        return getNewLDAPAttributes(requestState, path, v).then(
+            new Function<Attribute, List<Attribute>, ResourceException>() {
+                @Override
+                public List<Attribute> apply(Attribute newLDAPAttribute) throws ResourceException {
+                    if (!writabilityPolicy.canCreate(ldapAttributeName)) {
+                        if (!newLDAPAttribute.isEmpty() && !writabilityPolicy.discardWrites()) {
+                            throw new BadRequestException(i18n("The request cannot be processed because it attempts "
+                                    + "to create the read-only field '%s'", path));
+                        }
+                        return Collections.emptyList();
+                    } else if (newLDAPAttribute.isEmpty()) {
+                        if (isRequired) {
+                            throw new BadRequestException(i18n("The request cannot be processed because it attempts "
+                                    + "to remove the required field '%s'", path));
+                        }
+                        return Collections.emptyList();
+                    }
+
+                    return singletonList(newLDAPAttribute);
+                }
+            });
     }
 
     @Override
-    void getLDAPAttributes(final Context c, final JsonPointer path, final JsonPointer subPath,
-            final Set<String> ldapAttributes) {
+    void getLDAPAttributes(final RequestState requestState, final JsonPointer path,
+            final JsonPointer subPath, final Set<String> ldapAttributes) {
         ldapAttributes.add(ldapAttributeName.toString());
     }
 
-    abstract void getNewLDAPAttributes(Context c, JsonPointer path, List<Object> newValues,
-            ResultHandler<Attribute> h);
+    abstract Promise<Attribute, ResourceException> getNewLDAPAttributes(
+                RequestState requestState, JsonPointer path, List<Object> newValues);
 
     abstract T getThis();
 
     @Override
-    void patch(final Context c, final JsonPointer path, final PatchOperation operation,
-            final ResultHandler<List<Modification>> h) {
+    Promise<List<Modification>, ResourceException> patch(
+                final RequestState requestState, final JsonPointer path, final PatchOperation operation) {
         try {
             final JsonPointer field = operation.getField();
             final JsonValue v = operation.getValue();
@@ -235,33 +253,95 @@
             if (newValues.isEmpty()) {
                 // Deleting the attribute.
                 if (isRequired) {
-                    h.handleError(new BadRequestException(i18n(
-                            "The request cannot be processed because it attempts to remove "
-                                    + "the required field '%s'", path)));
+                    return Promises.<List<Modification>, ResourceException> newExceptionPromise(
+                            new BadRequestException(i18n(
+                                "The request cannot be processed because it attempts to remove the required field '%s'",
+                                path)));
                 } else {
-                    h.handleResult(singletonList(new Modification(modType,
-                            emptyAttribute(ldapAttributeName))));
+                    return Promises.newResultPromise(
+                        singletonList(new Modification(modType, emptyAttribute(ldapAttributeName))));
                 }
             } else {
-                getNewLDAPAttributes(c, path, newValues, transform(
-                        new Function<Attribute, List<Modification>, NeverThrowsException>() {
+                return getNewLDAPAttributes(requestState, path, newValues)
+                        .then(new Function<Attribute, List<Modification>, ResourceException>() {
                             @Override
                             public List<Modification> apply(final Attribute value) {
                                 return singletonList(new Modification(modType, value));
                             }
-                        }, h));
+                        });
             }
         } catch (final RuntimeException e) {
-            h.handleError(asResourceException(e));
+            return Promises.newExceptionPromise(asResourceException(e));
         } catch (final ResourceException e) {
-            h.handleError(e);
+            return Promises.newExceptionPromise(e);
         }
     }
 
     @Override
-    void update(final Context c, final JsonPointer path, final Entry e, final JsonValue v,
-            final ResultHandler<List<Modification>> h) {
-        getNewLDAPAttributes(c, path, v, updateAttributeHandler(path, e, h));
+    Promise<List<Modification>, ResourceException> update(
+            final RequestState requestState, final JsonPointer path, final Entry e, final JsonValue v) {
+        return getNewLDAPAttributes(requestState, path, v).then(
+            new Function<Attribute, List<Modification>, ResourceException>() {
+                @Override
+                public List<Modification> apply(final Attribute newLDAPAttribute) throws ResourceException {
+                    // Get the existing LDAP attribute.
+                    final Attribute tmp = e.getAttribute(ldapAttributeName);
+                    final Attribute oldLDAPAttribute = tmp != null ? tmp : emptyAttribute(ldapAttributeName);
+                    /*
+                     * If the attribute is read-only then handle the following cases:
+                     * 1) new values are provided and they are the same as the existing values
+                     * 2) no new values are provided.
+                     */
+                    if (!writabilityPolicy.canWrite(ldapAttributeName)) {
+                        if (newLDAPAttribute.isEmpty()
+                                || newLDAPAttribute.equals(oldLDAPAttribute)
+                                || writabilityPolicy.discardWrites()) {
+                            // No change.
+                            return Collections.emptyList();
+                        }
+                        throw new BadRequestException(i18n(
+                            "The request cannot be processed because it attempts to modify the read-only field '%s'",
+                            path));
+                    }
+
+                    if (oldLDAPAttribute.isEmpty() && newLDAPAttribute.isEmpty()) {
+                        // No change.
+                        return Collections.emptyList();
+                    } else if (oldLDAPAttribute.isEmpty()) {
+                        // The attribute is being added.
+                        return singletonList(new Modification(ModificationType.REPLACE, newLDAPAttribute));
+                    } else if (newLDAPAttribute.isEmpty()) {
+                        // The attribute is being deleted - this is not allowed if the attribute is required.
+                        if (isRequired) {
+                            throw new BadRequestException(i18n(
+                                "The request cannot be processed because it attempts to remove the required field '%s'",
+                                path));
+                        }
+                        return singletonList(new Modification(ModificationType.REPLACE, newLDAPAttribute));
+                    } else {
+                        /*
+                         * We could do a replace, but try to save bandwidth and send diffs instead.
+                         * Perform deletes first in case we don't have an appropriate normalizer:
+                         * permissive add(x) followed by delete(x) is destructive, whereas
+                         * delete(x) followed by add(x) is idempotent when adding/removing the same value.
+                         */
+                        final List<Modification> modifications = new ArrayList<>(2);
+
+                        final Attribute deletedValues = new LinkedAttribute(oldLDAPAttribute);
+                        deletedValues.removeAll(newLDAPAttribute);
+                        if (!deletedValues.isEmpty()) {
+                            modifications.add(new Modification(ModificationType.DELETE, deletedValues));
+                        }
+
+                        final Attribute addedValues = new LinkedAttribute(newLDAPAttribute);
+                        addedValues.removeAll(oldLDAPAttribute);
+                        if (!addedValues.isEmpty()) {
+                            modifications.add(new Modification(ModificationType.ADD, addedValues));
+                        }
+                        return modifications;
+                    }
+                }
+            });
     }
 
     private List<Object> asList(final JsonValue v, final List<Object> defaultValues) {
@@ -290,142 +370,21 @@
         }
     }
 
-    private ResultHandler<Attribute> createAttributeHandler(final JsonPointer path,
-            final ResultHandler<List<Attribute>> h) {
-        return new ResultHandler<Attribute>() {
-            @Override
-            public void handleError(final ResourceException error) {
-                h.handleError(error);
-            }
-
-            @Override
-            public void handleResult(final Attribute newLDAPAttribute) {
-                if (!writabilityPolicy.canCreate(ldapAttributeName)) {
-                    if (newLDAPAttribute.isEmpty() || writabilityPolicy.discardWrites()) {
-                        h.handleResult(Collections.<Attribute> emptyList());
-                    } else {
-                        h.handleError(new BadRequestException(i18n(
-                                "The request cannot be processed because it attempts to create "
-                                        + "the read-only field '%s'", path)));
-                    }
-                } else if (newLDAPAttribute.isEmpty()) {
-                    if (isRequired) {
-                        h.handleError(new BadRequestException(i18n(
-                                "The request cannot be processed because it attempts to remove "
-                                        + "the required field '%s'", path)));
-                        return;
-                    } else {
-                        h.handleResult(Collections.<Attribute> emptyList());
-                    }
-                } else {
-                    h.handleResult(singletonList(newLDAPAttribute));
-                }
-            }
-        };
-    }
-
-    private void getNewLDAPAttributes(final Context c, final JsonPointer path, final JsonValue v,
-            final ResultHandler<Attribute> attributeHandler) {
+    private Promise<Attribute, ResourceException> getNewLDAPAttributes(
+            final RequestState requestState, final JsonPointer path, final JsonValue v) {
         try {
             // Ensure that the value is of the correct type.
             checkSchema(path, v);
             final List<Object> newValues = asList(v, defaultJSONValues);
             if (newValues.isEmpty()) {
                 // Skip sub-class implementation if there are no values.
-                attributeHandler.handleResult(emptyAttribute(ldapAttributeName));
+                return Promises.newResultPromise(emptyAttribute(ldapAttributeName));
             } else {
-                getNewLDAPAttributes(c, path, newValues, attributeHandler);
+                return getNewLDAPAttributes(requestState, path, newValues);
             }
         } catch (final Exception ex) {
-            attributeHandler.handleError(asResourceException(ex));
+            return Promises.newExceptionPromise(asResourceException(ex));
         }
     }
 
-    private ResultHandler<Attribute> updateAttributeHandler(final JsonPointer path, final Entry e,
-            final ResultHandler<List<Modification>> h) {
-        // Get the existing LDAP attribute.
-        final Attribute tmp = e.getAttribute(ldapAttributeName);
-        final Attribute oldLDAPAttribute = tmp != null ? tmp : emptyAttribute(ldapAttributeName);
-        return new ResultHandler<Attribute>() {
-            @Override
-            public void handleError(final ResourceException error) {
-                h.handleError(error);
-            }
-
-            @Override
-            public void handleResult(final Attribute newLDAPAttribute) {
-                /*
-                 * If the attribute is read-only then handle the following
-                 * cases:
-                 *
-                 * 1) new values are provided and they are the same as the
-                 * existing values
-                 *
-                 * 2) no new values are provided.
-                 */
-                if (!writabilityPolicy.canWrite(ldapAttributeName)) {
-                    if (newLDAPAttribute.isEmpty() || newLDAPAttribute.equals(oldLDAPAttribute)
-                            || writabilityPolicy.discardWrites()) {
-                        // No change.
-                        h.handleResult(Collections.<Modification> emptyList());
-                    } else {
-                        h.handleError(new BadRequestException(i18n(
-                                "The request cannot be processed because it attempts to modify "
-                                        + "the read-only field '%s'", path)));
-                    }
-                } else {
-                    // Compute the changes to the attribute.
-                    final List<Modification> modifications;
-                    if (oldLDAPAttribute.isEmpty() && newLDAPAttribute.isEmpty()) {
-                        // No change.
-                        modifications = Collections.<Modification> emptyList();
-                    } else if (oldLDAPAttribute.isEmpty()) {
-                        // The attribute is being added.
-                        modifications =
-                                singletonList(new Modification(ModificationType.REPLACE,
-                                        newLDAPAttribute));
-                    } else if (newLDAPAttribute.isEmpty()) {
-                        /*
-                         * The attribute is being deleted - this is not allowed
-                         * if the attribute is required.
-                         */
-                        if (isRequired) {
-                            h.handleError(new BadRequestException(i18n(
-                                    "The request cannot be processed because it attempts to remove "
-                                            + "the required field '%s'", path)));
-                            return;
-                        } else {
-                            modifications =
-                                    singletonList(new Modification(ModificationType.REPLACE,
-                                            newLDAPAttribute));
-                        }
-                    } else {
-                        /*
-                         * We could do a replace, but try to save bandwidth and
-                         * send diffs instead. Perform deletes first in case we
-                         * don't have an appropriate normalizer: permissive
-                         * add(x) followed by delete(x) is destructive, whereas
-                         * delete(x) followed by add(x) is idempotent when
-                         * adding/removing the same value.
-                         */
-                        modifications = new ArrayList<>(2);
-
-                        final Attribute deletedValues = new LinkedAttribute(oldLDAPAttribute);
-                        deletedValues.removeAll(newLDAPAttribute);
-                        if (!deletedValues.isEmpty()) {
-                            modifications.add(new Modification(ModificationType.DELETE,
-                                    deletedValues));
-                        }
-
-                        final Attribute addedValues = new LinkedAttribute(newLDAPAttribute);
-                        addedValues.removeAll(oldLDAPAttribute);
-                        if (!addedValues.isEmpty()) {
-                            modifications.add(new Modification(ModificationType.ADD, addedValues));
-                        }
-                    }
-                    h.handleResult(modifications);
-                }
-            }
-        };
-    }
 }

--
Gitblit v1.10.0