From b0a81eda9a0b2717e90dee49af53adc71f7cc3dc Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 31 Jan 2013 18:01:23 +0000
Subject: [PATCH] Fix OPENDJ-690: Rest2LDAP - Implement basic search support

---
 opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java |  150 ++++++++++++++++++++++++++------------------------
 1 files changed, 78 insertions(+), 72 deletions(-)

diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
index b69fcf8..9d7f367 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
@@ -11,26 +11,29 @@
  * Header, with the fields enclosed by brackets [] replaced by your own identifying
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
- * Copyright 2012 ForgeRock AS.
+ * Copyright 2012-2013 ForgeRock AS.
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Utils.accumulate;
+import static org.forgerock.opendj.rest2ldap.Utils.transform;
+
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import org.forgerock.json.fluent.JsonPointer;
 import org.forgerock.json.fluent.JsonValue;
-import org.forgerock.json.resource.ResourceException;
 import org.forgerock.json.resource.ResultHandler;
-import org.forgerock.json.resource.ServerContext;
 import org.forgerock.opendj.ldap.Attribute;
 import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.Filter;
+import org.forgerock.opendj.ldap.Function;
 
 /**
  * An attribute mapper which combines the results of a set of subordinate
@@ -62,9 +65,10 @@
      * {@inheritDoc}
      */
     @Override
-    public void getLDAPAttributes(final JsonPointer jsonAttribute, final Set<String> ldapAttributes) {
+    public void getLDAPAttributes(final Context c, final JsonPointer jsonAttribute,
+            final Set<String> ldapAttributes) {
         for (final AttributeMapper attribute : attributeMappers) {
-            attribute.getLDAPAttributes(jsonAttribute, ldapAttributes);
+            attribute.getLDAPAttributes(c, jsonAttribute, ldapAttributes);
         }
     }
 
@@ -72,49 +76,68 @@
      * {@inheritDoc}
      */
     @Override
-    public void toJSON(final ServerContext c, final Entry e,
-            final ResultHandler<Map<String, Object>> h) {
-        final ResultHandler<Map<String, Object>> resultAccumulater = new ResultHandler<Map<String, Object>>() {
-            private final AtomicInteger latch = new AtomicInteger(attributeMappers.size());
-            private final List<Map<String, Object>> results = new ArrayList<Map<String, Object>>(
-                    latch.get());
+    public void getLDAPFilter(final Context c, final FilterType type,
+            final JsonPointer jsonAttribute, final String operator, final Object valueAssertion,
+            final ResultHandler<Filter> h) {
+        final ResultHandler<Filter> handler =
+                accumulate(attributeMappers.size(), transform(
+                        new Function<List<Filter>, Filter, Void>() {
+                            @Override
+                            public Filter apply(final List<Filter> value, final Void p) {
+                                // Remove unmapped filters and combine using logical-OR.
+                                final Iterator<Filter> i = value.iterator();
+                                while (i.hasNext()) {
+                                    final Filter f = i.next();
+                                    if (f == null) {
+                                        // No mapping so remove.
+                                        i.remove();
+                                    } else if (f == c.getConfig().getFalseFilter()) {
+                                        return c.getConfig().getFalseFilter();
+                                    } else if (f == c.getConfig().getTrueFilter()) {
+                                        return c.getConfig().getTrueFilter();
+                                    }
+                                }
+                                switch (value.size()) {
+                                case 0:
+                                    // No mappings found.
+                                    return null;
+                                case 1:
+                                    return value.get(0);
+                                default:
+                                    return Filter.or(value);
+                                }
+                            }
+                        }, h));
+        for (final AttributeMapper subMapper : attributeMappers) {
+            subMapper.getLDAPFilter(c, type, jsonAttribute, operator, valueAssertion, handler);
+        }
+    }
 
-            @Override
-            public void handleError(final ResourceException e) {
-                // Ensure that handler is only invoked once.
-                if (latch.getAndSet(0) > 0) {
-                    h.handleError(e);
-                }
-            }
-
-            @Override
-            public void handleResult(final Map<String, Object> result) {
-                if (result != null && !result.isEmpty()) {
-                    synchronized (this) {
-                        results.add(result);
-                    }
-                }
-                if (latch.decrementAndGet() == 0) {
-                    final Map<String, Object> mergeResult;
-                    switch (results.size()) {
-                    case 0:
-                        mergeResult = Collections.<String, Object> emptyMap();
-                        break;
-                    case 1:
-                        mergeResult = results.get(0);
-                        break;
-                    default:
-                        mergeResult = new LinkedHashMap<String, Object>();
-                        mergeJsonValues(results, mergeResult);
-                        break;
-                    }
-                    h.handleResult(mergeResult);
-                }
-            }
-        };
-
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void toJSON(final Context c, final Entry e, final ResultHandler<Map<String, Object>> h) {
+        final ResultHandler<Map<String, Object>> handler =
+                accumulate(attributeMappers.size(), transform(
+                        new Function<List<Map<String, Object>>, Map<String, Object>, Void>() {
+                            @Override
+                            public Map<String, Object> apply(final List<Map<String, Object>> value,
+                                    final Void p) {
+                                switch (value.size()) {
+                                case 0:
+                                    return Collections.<String, Object> emptyMap();
+                                case 1:
+                                    return value.get(0) != null ? value.get(0) : Collections
+                                            .<String, Object> emptyMap();
+                                default:
+                                    return mergeJsonValues(value,
+                                            new LinkedHashMap<String, Object>());
+                                }
+                            }
+                        }, h));
         for (final AttributeMapper mapper : attributeMappers) {
-            mapper.toJSON(c, e, resultAccumulater);
+            mapper.toJSON(c, e, handler);
         }
     }
 
@@ -122,21 +145,10 @@
      * {@inheritDoc}
      */
     @Override
-    public void toLDAP(final ServerContext c, final JsonValue v,
-            final ResultHandler<List<Attribute>> h) {
+    public void toLDAP(final Context c, final JsonValue v, final ResultHandler<List<Attribute>> h) {
         // TODO Auto-generated method stub
-
     }
 
-    /**
-     * Merge one JSON value into another.
-     *
-     * @param srcValue
-     *            The source value.
-     * @param dstValue
-     *            The destination value, into which which the value should be
-     *            merged.
-     */
     @SuppressWarnings("unchecked")
     private void mergeJsonValue(final Map<String, Object> srcValue,
             final Map<String, Object> dstValue) {
@@ -150,8 +162,8 @@
             } else if ((existingValue instanceof Map) && (newValue instanceof Map)) {
                 // Merge two maps - create a new Map, in case the existing one
                 // is unmodifiable.
-                existingValue = new LinkedHashMap<String, Object>(
-                        (Map<String, Object>) existingValue);
+                existingValue =
+                        new LinkedHashMap<String, Object>((Map<String, Object>) existingValue);
                 mergeJsonValue((Map<String, Object>) newValue, (Map<String, Object>) existingValue);
             } else if ((existingValue instanceof List) && (newValue instanceof List)) {
                 // Merge two lists- create a new List, in case the existing one
@@ -166,19 +178,13 @@
         }
     }
 
-    /**
-     * Merge the provided list of JSON values into a single value.
-     *
-     * @param srcValues
-     *            The source values.
-     * @param dstValue
-     *            The destination value, into which which the values should be
-     *            merged.
-     */
-    private void mergeJsonValues(final List<Map<String, Object>> srcValues,
+    private Map<String, Object> mergeJsonValues(final List<Map<String, Object>> srcValues,
             final Map<String, Object> dstValue) {
         for (final Map<String, Object> value : srcValues) {
-            mergeJsonValue(value, dstValue);
+            if (value != null) {
+                mergeJsonValue(value, dstValue);
+            }
         }
+        return dstValue;
     }
 }

--
Gitblit v1.10.0