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/ObjectAttributeMapper.java |  171 ++++++++++++++++++++++++++++----------------------------
 1 files changed, 85 insertions(+), 86 deletions(-)

diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java
index 9b4124c..03cc53a 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java
@@ -15,6 +15,12 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.json.resource.PatchOperation.operation;
+import static org.forgerock.opendj.ldap.Filter.alwaysFalse;
+import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
+import static org.forgerock.opendj.rest2ldap.Utils.i18n;
+import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
+
 import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -23,27 +29,20 @@
 import java.util.Map;
 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.PatchOperation;
 import org.forgerock.json.resource.ResourceException;
-import org.forgerock.json.resource.ResultHandler;
 import org.forgerock.opendj.ldap.Attribute;
 import org.forgerock.opendj.ldap.Entry;
 import org.forgerock.opendj.ldap.Filter;
 import org.forgerock.opendj.ldap.Modification;
 import org.forgerock.util.Function;
-import org.forgerock.util.promise.NeverThrowsException;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.Promises;
 
-import static org.forgerock.json.resource.PatchOperation.*;
-import static org.forgerock.opendj.ldap.Filter.*;
-import static org.forgerock.opendj.rest2ldap.Rest2LDAP.*;
-import static org.forgerock.opendj.rest2ldap.Utils.*;
-
-/**
- * An attribute mapper which maps JSON objects to LDAP attributes.
- */
+/** An attribute mapper which maps JSON objects to LDAP attributes. */
 public final class ObjectAttributeMapper extends AttributeMapper {
 
     private static final class Mapping {
@@ -88,8 +87,8 @@
     }
 
     @Override
-    void create(final Context c, final JsonPointer path, final JsonValue v,
-            final ResultHandler<List<Attribute>> h) {
+    Promise<List<Attribute>, ResourceException> create(
+            final RequestState requestState, final JsonPointer path, final JsonValue v) {
         try {
             /*
              * First check that the JSON value is an object and that the fields
@@ -98,66 +97,67 @@
             final Map<String, Mapping> missingMappings = checkMapping(path, v);
 
             // Accumulate the results of the subordinate mappings.
-            final ResultHandler<List<Attribute>> handler = accumulator(h);
+            final List<Promise<List<Attribute>, ResourceException>> promises = new ArrayList<>();
 
             // Invoke mappings for which there are values provided.
             if (v != null && !v.isNull()) {
                 for (final Map.Entry<String, Object> me : v.asMap().entrySet()) {
                     final Mapping mapping = getMapping(me.getKey());
                     final JsonValue subValue = new JsonValue(me.getValue());
-                    mapping.mapper.create(c, path.child(me.getKey()), subValue, handler);
+                    promises.add(mapping.mapper.create(requestState, path.child(me.getKey()), subValue));
                 }
             }
 
             // Invoke mappings for which there were no values provided.
             for (final Mapping mapping : missingMappings.values()) {
-                mapping.mapper.create(c, path.child(mapping.name), null, handler);
+                promises.add(mapping.mapper.create(requestState, path.child(mapping.name), null));
             }
+
+            return Promises.when(promises)
+                           .then(this.<Attribute> accumulateResults());
         } catch (final Exception e) {
-            h.handleError(asResourceException(e));
+            return Promises.newExceptionPromise(asResourceException(e));
         }
     }
 
     @Override
-    void getLDAPAttributes(final Context c, final JsonPointer path, final JsonPointer subPath,
+    void getLDAPAttributes(final RequestState requestState, final JsonPointer path, final JsonPointer subPath,
             final Set<String> ldapAttributes) {
         if (subPath.isEmpty()) {
             // Request all subordinate mappings.
             for (final Mapping mapping : mappings.values()) {
-                mapping.mapper.getLDAPAttributes(c, path.child(mapping.name), subPath,
-                        ldapAttributes);
+                mapping.mapper.getLDAPAttributes(requestState, path.child(mapping.name), subPath, ldapAttributes);
             }
         } else {
             // Request single subordinate mapping.
             final Mapping mapping = getMapping(subPath);
             if (mapping != null) {
-                mapping.mapper.getLDAPAttributes(c, path.child(subPath.get(0)), subPath
-                        .relativePointer(), ldapAttributes);
+                mapping.mapper.getLDAPAttributes(
+                        requestState, path.child(subPath.get(0)), subPath.relativePointer(), ldapAttributes);
             }
         }
     }
 
     @Override
-    void getLDAPFilter(final Context c, final JsonPointer path, final JsonPointer subPath,
-            final FilterType type, final String operator, final Object valueAssertion,
-            final ResultHandler<Filter> h) {
+    Promise<Filter, ResourceException> getLDAPFilter(final RequestState requestState, final JsonPointer path,
+            final JsonPointer subPath, final FilterType type, final String operator, final Object valueAssertion) {
         final Mapping mapping = getMapping(subPath);
         if (mapping != null) {
-            mapping.mapper.getLDAPFilter(c, path.child(subPath.get(0)), subPath.relativePointer(),
-                    type, operator, valueAssertion, h);
+            return mapping.mapper.getLDAPFilter(requestState, path.child(subPath.get(0)),
+                    subPath.relativePointer(), type, operator, valueAssertion);
         } else {
             /*
              * Either the filter targeted the entire object (i.e. it was "/"),
              * or it targeted an unrecognized attribute within the object.
              * Either way, the filter will never match.
              */
-            h.handleResult(alwaysFalse());
+            return Promises.newResultPromise(alwaysFalse());
         }
     }
 
     @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();
@@ -168,11 +168,10 @@
                  * by allowing the JSON value to be a partial object and
                  * add/remove/replace only the provided values.
                  */
-                final Map<String, Mapping> missingMappings = checkMapping(path, v);
+                checkMapping(path, v);
 
                 // Accumulate the results of the subordinate mappings.
-                final ResultHandler<List<Modification>> handler =
-                        accumulator(mappings.size() - missingMappings.size(), h);
+                final List<Promise<List<Modification>, ResourceException>> promises = new ArrayList<>();
 
                 // Invoke mappings for which there are values provided.
                 if (!v.isNull()) {
@@ -181,9 +180,12 @@
                         final JsonValue subValue = new JsonValue(me.getValue());
                         final PatchOperation subOperation =
                                 operation(operation.getOperation(), field /* empty */, subValue);
-                        mapping.mapper.patch(c, path.child(me.getKey()), subOperation, handler);
+                        promises.add(mapping.mapper.patch(requestState, path.child(me.getKey()), subOperation));
                     }
                 }
+
+                return Promises.when(promises)
+                               .then(this.<Modification> accumulateResults());
             } else {
                 /*
                  * The patch operation targets a subordinate field. Create a new
@@ -199,92 +201,92 @@
                 }
                 final PatchOperation subOperation =
                         operation(operation.getOperation(), field.relativePointer(), v);
-                mapping.mapper.patch(c, path.child(fieldName), subOperation, h);
+                return mapping.mapper.patch(requestState, path.child(fieldName), subOperation);
             }
         } catch (final Exception ex) {
-            h.handleError(asResourceException(ex));
+            return Promises.newExceptionPromise(asResourceException(ex));
         }
     }
 
     @Override
-    void read(final Context c, final JsonPointer path, final Entry e,
-            final ResultHandler<JsonValue> h) {
+    Promise<JsonValue, ResourceException> read(final RequestState requestState, final JsonPointer path, final Entry e) {
         /*
          * Use an accumulator which will aggregate the results from the
          * subordinate mappers into a single list. On completion, the
          * accumulator combines the results into a single JSON map object.
          */
-        final ResultHandler<Map.Entry<String, JsonValue>> handler =
-                accumulate(mappings.size(), transform(
-                        new Function<List<Map.Entry<String, JsonValue>>, JsonValue, NeverThrowsException>() {
-                            @Override
-                            public JsonValue apply(final List<Map.Entry<String, JsonValue>> value) {
-                                if (value.isEmpty()) {
-                                    /*
-                                     * No subordinate attributes, so omit the
-                                     * entire JSON object from the resource.
-                                     */
-                                    return null;
-                                } else {
-                                    // Combine the sub-attributes into a single JSON object.
-                                    final Map<String, Object> result = new LinkedHashMap<>(value.size());
-                                    for (final Map.Entry<String, JsonValue> e : value) {
-                                        result.put(e.getKey(), e.getValue().getObject());
-                                    }
-                                    return new JsonValue(result);
-                                }
-                            }
-                        }, h));
+        final List<Promise<Map.Entry<String, JsonValue>, ResourceException>> promises =
+                new ArrayList<>(mappings.size());
 
         for (final Mapping mapping : mappings.values()) {
-            mapping.mapper.read(c, path.child(mapping.name), e, transform(
-                    new Function<JsonValue, Map.Entry<String, JsonValue>, NeverThrowsException>() {
+            promises.add(mapping.mapper.read(requestState, path.child(mapping.name), e)
+                    .then(new Function<JsonValue, Map.Entry<String, JsonValue>, ResourceException>() {
                         @Override
                         public Map.Entry<String, JsonValue> apply(final JsonValue value) {
-                            return value != null ? new SimpleImmutableEntry<String, JsonValue>(
-                                    mapping.name, value) : null;
+                            return value != null ? new SimpleImmutableEntry<String, JsonValue>(mapping.name, value)
+                                                 : null;
                         }
-                    }, handler));
+                    }));
         }
+
+        return Promises.when(promises)
+                .then(new Function<List<Map.Entry<String, JsonValue>>, JsonValue, ResourceException>() {
+                    @Override
+                    public JsonValue apply(final List<Map.Entry<String, JsonValue>> value) {
+                        if (value.isEmpty()) {
+                            /*
+                             * No subordinate attributes, so omit the entire
+                             * JSON object from the resource.
+                             */
+                            return null;
+                        } else {
+                            // Combine the sub-attributes into a single JSON object.
+                            final Map<String, Object> result = new LinkedHashMap<>(value.size());
+                            for (final Map.Entry<String, JsonValue> e : value) {
+                                if (e != null) {
+                                    result.put(e.getKey(), e.getValue().getObject());
+                                }
+                            }
+                            return new JsonValue(result);
+                        }
+                    }
+                });
     }
 
     @Override
-    void update(final Context c, final JsonPointer path, final Entry e, final JsonValue v,
-            final ResultHandler<List<Modification>> h) {
+    Promise<List<Modification>, ResourceException> update(
+            final RequestState requestState, final JsonPointer path, final Entry e, final JsonValue v) {
         try {
-            /*
-             * First check that the JSON value is an object and that the fields
-             * it contains are known by this mapper.
-             */
+            // First check that the JSON value is an object and that the fields
+            // it contains are known by this mapper.
             final Map<String, Mapping> missingMappings = checkMapping(path, v);
 
             // Accumulate the results of the subordinate mappings.
-            final ResultHandler<List<Modification>> handler = accumulator(h);
+            final List<Promise<List<Modification>, ResourceException>> promises = new ArrayList<>();
 
             // Invoke mappings for which there are values provided.
             if (v != null && !v.isNull()) {
                 for (final Map.Entry<String, Object> me : v.asMap().entrySet()) {
                     final Mapping mapping = getMapping(me.getKey());
                     final JsonValue subValue = new JsonValue(me.getValue());
-                    mapping.mapper.update(c, path.child(me.getKey()), e, subValue, handler);
+                    promises.add(mapping.mapper.update(requestState, path.child(me.getKey()), e, subValue));
                 }
             }
 
             // Invoke mappings for which there were no values provided.
             for (final Mapping mapping : missingMappings.values()) {
-                mapping.mapper.update(c, path.child(mapping.name), e, null, handler);
+                promises.add(mapping.mapper.update(requestState, path.child(mapping.name), e, null));
             }
+
+            return Promises.when(promises)
+                           .then(this.<Modification> accumulateResults());
         } catch (final Exception ex) {
-            h.handleError(asResourceException(ex));
+            return Promises.newExceptionPromise(asResourceException(ex));
         }
     }
 
-    private <T> ResultHandler<List<T>> accumulator(final ResultHandler<List<T>> h) {
-        return accumulator(mappings.size(), h);
-    }
-
-    private <T> ResultHandler<List<T>> accumulator(final int size, final ResultHandler<List<T>> h) {
-        return accumulate(size, transform(new Function<List<List<T>>, List<T>, NeverThrowsException>() {
+    private <T> Function<List<List<T>>, List<T>, ResourceException> accumulateResults() {
+        return new Function<List<List<T>>, List<T>, ResourceException>() {
             @Override
             public List<T> apply(final List<List<T>> value) {
                 switch (value.size()) {
@@ -300,13 +302,10 @@
                     return attributes;
                 }
             }
-        }, h));
+        };
     }
 
-    /**
-     * Fail immediately if the JSON value has the wrong type or contains unknown
-     * attributes.
-     */
+    /** Fail immediately if the JSON value has the wrong type or contains unknown attributes. */
     private Map<String, Mapping> checkMapping(final JsonPointer path, final JsonValue v)
             throws ResourceException {
         final Map<String, Mapping> missingMappings = new LinkedHashMap<>(mappings);

--
Gitblit v1.10.0